我正在尝试首次使用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对象?在这种情况下,处理Model状态的最佳方法是什么?
一个实际的解决方案可能是编写代码以在模型本身中序列化模型,并为每个getNextState()
保存,但这将意味着在模型中使用Android调用(并降低其可测试性)。
答案 0 :(得分:1)
您应该使用其他持久性机制。 onSaveInstanceState()确实用于操作系统由于配置/方向更改等原因需要还原UI状态的情况。这不是通用的存储机制。
该模型是持久保存数据的正确位置,并且您应该尽可能使模型与Android无关,这是正确的。您可以做的是定义一个代表您的持久性要求的接口:
interface SampleRepo{
fun saveData(...)
fun getData(...)
}
然后您在类中首选的持久性机制(例如SharedPreferences,SQlite等)将实现该接口。这是隐藏您的Android专用内容的地方。
class SharedPrefRepo : SampleRepo{
override fun saveData(...)
override fun getData(...)
}
理想情况下,您需要某种注入机制,以便可以将上述实例注入模型类(例如Dagger)。它需要更多的管道代码,但这就是松耦合的代价。对于更简单的应用程序(例如您正在执行的操作),所有这些都是过分的。但是,如果您要研究适当的Android应用程序架构和松散耦合,那么值得探索如何正确进行。