How to restore Model state in MVP?What are MVP and MVC and what is the difference?How do save an Android Activity state using save instance state?Why is the Android emulator so slow? How can we speed up the Android emulator?Restore State after process is killedWhy should I override onSavedInstanceState for retrieve instance state in android?MVP Android - Where to save the view state?Tensorflow: how to save/restore a model?Pass bundle intent in android using MVPWhat is the best way to restore state in MVP?restoring state in a presenter with MVP

Should I warn a new PhD Student?

Why is implicit conversion not ambiguous for non-primitive types?

Do native speakers use "ultima" and "proxima" frequently in spoken English?

How would a solely written language work mechanically

Center page as a whole without centering each element individually

Weird lines in Microsoft Word

Is there a distance limit for minecart tracks?

Sort with assumptions

How to get directions in deep space?

What is the period/term used describe Giuseppe Arcimboldo's style of painting?

Using an older 200A breaker panel on a 60A feeder circuit from house?

What is the purpose of using a decision tree?

What (if any) is the reason to buy in small local stores?

Rendered textures different to 3D View

Make a Bowl of Alphabet Soup

What properties make a magic weapon befit a Rogue more than a DEX-based Fighter?

What is the meaning of "You've never met a graph you didn't like?"

I keep switching characters, how do I stop?

Derivative of an interpolated function

Why do Radio Buttons not fill the entire outer circle?

Reasons for having MCU pin-states default to pull-up/down out of reset

How to preserve electronics (computers, ipads, phones) for hundreds of years?

A seasonal riddle

Would this string work as string?



How to restore Model state in MVP?


What are MVP and MVC and what is the difference?How do save an Android Activity state using save instance state?Why is the Android emulator so slow? How can we speed up the Android emulator?Restore State after process is killedWhy should I override onSavedInstanceState for retrieve instance state in android?MVP Android - Where to save the view state?Tensorflow: how to save/restore a model?Pass bundle intent in android using MVPWhat is the best way to restore state in MVP?restoring state in a presenter with MVP













0















App Descripion



I'm trying to implement for my first time an Android app with MVP, where a message (taken from a pool of messages) is displayed and it's changed when the user click on the screen. Once all message have been displayed, the process will start over (following the same order of messages). A requirement is to display the same message if the app is closed/reopened. So, we have to implement some implement some store/restore state mechanism in the MVP model.



Here's a basic demo of the app:



enter image description here



MVP Design



I've implemented this MVP for this app as follow:



  1. The Model takes care of what it will be the next message (it implements the application state).

  2. The Presenter decides when to ask for the next message (to update the state), depending on the received events from the user (through the View).

  3. The View decides how to show the actual message and communicates events from the user (clicks on the screen) to the presenter. In addition, since the View is also the 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).

Some Code



(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()




The Problem / My question



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).










share|improve this question




























    0















    App Descripion



    I'm trying to implement for my first time an Android app with MVP, where a message (taken from a pool of messages) is displayed and it's changed when the user click on the screen. Once all message have been displayed, the process will start over (following the same order of messages). A requirement is to display the same message if the app is closed/reopened. So, we have to implement some implement some store/restore state mechanism in the MVP model.



    Here's a basic demo of the app:



    enter image description here



    MVP Design



    I've implemented this MVP for this app as follow:



    1. The Model takes care of what it will be the next message (it implements the application state).

    2. The Presenter decides when to ask for the next message (to update the state), depending on the received events from the user (through the View).

    3. The View decides how to show the actual message and communicates events from the user (clicks on the screen) to the presenter. In addition, since the View is also the 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).

    Some Code



    (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()




    The Problem / My question



    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).










    share|improve this question


























      0












      0








      0








      App Descripion



      I'm trying to implement for my first time an Android app with MVP, where a message (taken from a pool of messages) is displayed and it's changed when the user click on the screen. Once all message have been displayed, the process will start over (following the same order of messages). A requirement is to display the same message if the app is closed/reopened. So, we have to implement some implement some store/restore state mechanism in the MVP model.



      Here's a basic demo of the app:



      enter image description here



      MVP Design



      I've implemented this MVP for this app as follow:



      1. The Model takes care of what it will be the next message (it implements the application state).

      2. The Presenter decides when to ask for the next message (to update the state), depending on the received events from the user (through the View).

      3. The View decides how to show the actual message and communicates events from the user (clicks on the screen) to the presenter. In addition, since the View is also the 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).

      Some Code



      (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()




      The Problem / My question



      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).










      share|improve this question
















      App Descripion



      I'm trying to implement for my first time an Android app with MVP, where a message (taken from a pool of messages) is displayed and it's changed when the user click on the screen. Once all message have been displayed, the process will start over (following the same order of messages). A requirement is to display the same message if the app is closed/reopened. So, we have to implement some implement some store/restore state mechanism in the MVP model.



      Here's a basic demo of the app:



      enter image description here



      MVP Design



      I've implemented this MVP for this app as follow:



      1. The Model takes care of what it will be the next message (it implements the application state).

      2. The Presenter decides when to ask for the next message (to update the state), depending on the received events from the user (through the View).

      3. The View decides how to show the actual message and communicates events from the user (clicks on the screen) to the presenter. In addition, since the View is also the 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).

      Some Code



      (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()




      The Problem / My question



      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).







      android design-patterns model mvp model-view






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 7 at 1:13







      justHelloWorld

















      asked Mar 7 at 1:00









      justHelloWorldjustHelloWorld

      2,26221757




      2,26221757






















          1 Answer
          1






          active

          oldest

          votes


















          1














          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(...)



          Ideally you'll want some injection mechanism so you can inject an instance of the above to your model class (e.g. Dagger). It requires some more plumbing code, but that is the price of loose coupling. For a simpler app, like what you're doing, all of this is overkill. But if you're trying to study proper Android app architecture and loose coupling then it's worth exploring how to do it properly.






          share|improve this answer

























          • Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

            – justHelloWorld
            Mar 7 at 8:06











          • 1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

            – Eugene
            Mar 7 at 8:39











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55034496%2fhow-to-restore-model-state-in-mvp%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          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(...)



          Ideally you'll want some injection mechanism so you can inject an instance of the above to your model class (e.g. Dagger). It requires some more plumbing code, but that is the price of loose coupling. For a simpler app, like what you're doing, all of this is overkill. But if you're trying to study proper Android app architecture and loose coupling then it's worth exploring how to do it properly.






          share|improve this answer

























          • Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

            – justHelloWorld
            Mar 7 at 8:06











          • 1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

            – Eugene
            Mar 7 at 8:39
















          1














          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(...)



          Ideally you'll want some injection mechanism so you can inject an instance of the above to your model class (e.g. Dagger). It requires some more plumbing code, but that is the price of loose coupling. For a simpler app, like what you're doing, all of this is overkill. But if you're trying to study proper Android app architecture and loose coupling then it's worth exploring how to do it properly.






          share|improve this answer

























          • Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

            – justHelloWorld
            Mar 7 at 8:06











          • 1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

            – Eugene
            Mar 7 at 8:39














          1












          1








          1







          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(...)



          Ideally you'll want some injection mechanism so you can inject an instance of the above to your model class (e.g. Dagger). It requires some more plumbing code, but that is the price of loose coupling. For a simpler app, like what you're doing, all of this is overkill. But if you're trying to study proper Android app architecture and loose coupling then it's worth exploring how to do it properly.






          share|improve this answer















          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(...)



          Ideally you'll want some injection mechanism so you can inject an instance of the above to your model class (e.g. Dagger). It requires some more plumbing code, but that is the price of loose coupling. For a simpler app, like what you're doing, all of this is overkill. But if you're trying to study proper Android app architecture and loose coupling then it's worth exploring how to do it properly.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Mar 7 at 6:21

























          answered Mar 7 at 3:41









          EugeneEugene

          17619




          17619












          • Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

            – justHelloWorld
            Mar 7 at 8:06











          • 1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

            – Eugene
            Mar 7 at 8:39


















          • Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

            – justHelloWorld
            Mar 7 at 8:06











          • 1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

            – Eugene
            Mar 7 at 8:39

















          Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

          – justHelloWorld
          Mar 7 at 8:06





          Thank you Eugene for your answer, I find it a very good solution. I still have some questions: 1. Every call to SampleRepo call will be performed in CircularModel model (the Model implementation), right? 2. When should we call saveData? At every getModelNextState()? Or only when we exit from the app?

          – justHelloWorld
          Mar 7 at 8:06













          1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

          – Eugene
          Mar 7 at 8:39






          1) - yes, correct. The Repo class will be inside the Model class. 2) - In this particular case I'd probably save it only when app exits or goes into background. But a real world implementation might want to keep such data constantly in sync so important state changes are persisted as soon as they happen. If your app crashed for example while it's doing something else and you only save when app goes to background then app might get restored with outdated data.

          – Eugene
          Mar 7 at 8:39




















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55034496%2fhow-to-restore-model-state-in-mvp%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          1928 у кіно

          Захаров Федір Захарович

          Ель Греко