메시지(메시지 풀에서 가져옴)가 표시되고 사용자가 화면을 클릭할 때 변경되는 MVP가 있는 Android 앱을 처음으로 구현하려고 합니다. 모든 메시지가 표시되면 프로세스가 다시 시작됩니다(같은 메시지 순서에 따라). 요구 사항은 앱이 닫히거나 다시 열릴 때 동일한 메시지를 표시하는 것입니다. 따라서 MVP 모델에서 일부 저장/복원 상태 메커니즘을 구현해야 합니다.
다음은 앱의 기본 데모입니다.
이 앱에 대해 이 MVP를 다음과 같이 구현했습니다.
MainActivity
, it takes care to instantiate the Presenter and Model implementations. Finally, it saves the Model state (as a Parcelable
) with onSaveInstanceState
(and also restores it).(Partial) View implementation:
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)
}
(Partial) Model implementation:
@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()
}
}
Since Presenter and Model should be "Android agnostic", saving the app state (i.e., the Model object) is taken care by the View. However, this breaks the principle where the View doesn't know the Model. My question is: how to save the Model object, without the View knowing the actual implementation of it? What is the best way to deal with the Model state in this scenario?
An actual solution could be to write the code to serialize the Model in the Model itself and save it for each getNextState()
, but this would mean use Android calls in the Model (and reduce its testability).
You should use a different persistence mechanism. The onSaveInstanceState() is really used for situations where the OS needs to restore UI state because of things like configuration / orientation changes. It's not a general purpose storage mechanism.
The model is the correct place to persist data and it is correct that you should try to keep the model as Android agnostic as possible. What you can do is define an interface that represents your persistence requirements:
interface SampleRepo{
fun saveData(...)
fun getData(...)
}
Then your preferred persistence mechanism (e.g. SharedPreferences, SQlite etc.) in a class implements that interface. This is where your Android specific stuff will be hidden.
class SharedPrefRepo : SampleRepo{
override fun saveData(...)
override fun getData(...)
}
이상적으로는 위의 인스턴스를 모델 클래스(예: Dagger)에 주입할 수 있도록 몇 가지 주입 메커니즘이 필요합니다. 더 많은 배관 코드가 필요하지만 느슨한 연결의 대가입니다. 당신이하고있는 것과 같은 더 간단한 앱의 경우이 모든 것이 과도합니다. 그러나 적절한 Android 앱 아키텍처와 느슨한 결합을 연구하려는 경우 올바르게 수행하는 방법을 탐구할 가치가 있습니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다