我正试图第一次实现一个带有MVP的Android应用程序,其中显示一条消息(取自消息池),当用户点击屏幕时它会被更改。显示所有消息后,该过程将重新开始(遵循相同的消息顺序)。如果应用程序已关闭/重新打开,则要求显示相同的消息。因此,我们必须在MVP模型中实现一些实现一些存储/恢复状态机制。
这是该应用程序的基本演示:
我为这个应用程序实现了这个MVP,如下所示:
MainActivity
,因此需要注意实例化Presenter和Model实现。最后,它使用Parcelable
保存模型状态(作为onSaveInstanceState
)(并且还恢复它)。(部分)查看实施:
class MainActivity : AppCompatActivity(), ViewMVC {
private lateinit var presenter: Presenter
private var model: Model? = CircularModel(LinkedList<State>(Arrays.asList(
State("First"),
State("Second"),
State("Third")
)))
override fun onCreate(savedInstanceState: Bundle?) {
if (savedInstanceState != null) {
model = savedInstanceState.getParcelable("model")
}
presenter = PresenterImpl(this, model!!)
}
override fun onSaveInstanceState(outState: Bundle?) {
outState?.putParcelable("model", model!!)
super.onSaveInstanceState(outState)
}
(部分)模型实施:
@Parcelize
class CircularModel constructor(var states: @RawValue Deque<State>?) : Model, Parcelable {
override fun getModelState(): State {
return states!!.peekFirst()
}
override fun getModelNextState(): State {
// Black magic happening here!
return getModelState()
}
}
由于Presenter和Model应该是“Android不可知”,因此View保存了应用程序状态(即Model对象)。但是,这打破了View不知道模型的原则。我的问题是:如何保存Model对象,而不知道View的实际执行情况呢?在这种情况下处理模型状态的最佳方法是什么?
一个实际的解决方案可能是编写代码以在模型本身中序列化模型并为每个getNextState()
保存它,但这意味着在模型中使用Android调用(并降低其可测试性)。
您应该使用不同的持久性机制。 onSaveInstanceState()实际上用于操作系统需要恢复UI状态的情况,因为配置/方向更改等。它不是通用的存储机制。
该模型是保存数据的正确位置,您应该尽可能地将模型保持为Android不可知是正确的。您可以做的是定义一个表示持久性要求的接口:
interface SampleRepo{
fun saveData(...)
fun getData(...)
}
然后,类中的首选持久性机制(例如,SharedPreferences,SQlite等)实现该接口。这是隐藏Android特定内容的地方。
class SharedPrefRepo : SampleRepo{
override fun saveData(...)
override fun getData(...)
}
理想情况下,您需要一些注入机制,以便您可以将上述实例注入模型类(例如Dagger)。它需要更多的管道代码,但这是松散耦合的代价。对于一个更简单的应用程序,就像你正在做的那样,所有这些都是矫枉过正的。但是,如果您正在尝试研究适当的Android应用程序架构和松散耦合,那么值得探索如何正确地进行操作。