The following problem arose in the Android application (in the application I use the MVP architecture): when switching from my application to another application that consumes a lot of resources, and then back to my application, all the Activity fields are erased and my Presenter is destroyed.

To save Presenter I tried to use

1) onRetainCustomNonConfigurationInstance ,

2) static field for Presenter object

3) as well as fragment to save the Presenter instance

But none of the above methods helped me in this situation. Although for example, if you use them when changing configurations (changing the orientation of the screen), all of the above methods work fine.

I assume that the inoperability of the above methods is related to the fact that when switching to another application, there is a sharp lack of resources and the android kills my application (kill app). Although the onDestroy method is not onDestroy when switching from one application to another.

Is it possible in my case how to solve this situation? Ideally, you should save the Presenter object so that when you destroy the application you can return it, the shared preference fits well here, but it works only with primitive objects, the presenter in this case cannot be saved with it.


An attempt to keep the Presenter in an external file was unsuccessful. Despite the fact that both Preseneter and ExperimentObject inside it implement the Serializable interface.

Activity:

public class MainActivity extends AppCompatActivity implements MainView {

 private static final String TAG = "MainActivity"; private MainPresenter mMainPresenter; private TextView mTextView_ShowVal; private Button mButton_IncreaseVal; private EditText mEditText_SetNum; private Button mButton_SetEditTextVal; private TextView mTextViewSomeText; @Override protected void onCreate(Bundle savedInstanceState) { Log.d(TAG, "ON CREATE"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindXML(); read(); if (mMainPresenter == null) { mMainPresenter = new MainPresenterImpl(this); } else { mMainPresenter.setNewViewObj(this); } mMainPresenter.onCreate(); setListeners(); } public void read(){ Log.d(TAG, "read()"); ObjectInputStream input; String filename = "testFilemost.srl"; try { input = new ObjectInputStream(new FileInputStream(new File(new File(getFilesDir(),"")+File.separator+filename))); mMainPresenter = (MainPresenter) input.readObject(); input.close(); } catch (StreamCorruptedException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public void write(){ Log.d(TAG, "write()"); String filename = "testFilemost.srl"; ObjectOutput out = null; try { out = new ObjectOutputStream(new FileOutputStream(new File(getFilesDir(),"")+File.separator+filename)); out.writeObject(mMainPresenter); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override protected void onPause() { Log.d(TAG, "ON PAUSE"); write(); mMainPresenter = null; read(); super.onPause(); } @Override protected void onStart() { Log.d(TAG, "ON START"); read(); super.onStart(); } @Override protected void onStop() { Log.d(TAG, "ON STOP"); super.onStop(); } @Override protected void onDestroy() { Log.d(TAG, "ON DESTROY"); super.onDestroy(); } @Override protected void onResume() { Log.d(TAG, "ON RESUME"); mMainPresenter.onResume(); super.onResume(); } @Override public String getTextEditText() { return mEditText_SetNum.getText().toString(); } @Override public void setTextTextView(String text) { Log.d(TAG, "text = " + text); mTextView_ShowVal.setText(text); } public void setListeners() { mButton_IncreaseVal.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mMainPresenter.executeClickIncreaseBtn(); } }); mButton_SetEditTextVal.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mMainPresenter.executeClickSetValBtn(); } }); } public void bindXML() { mTextView_ShowVal = (TextView) findViewById(R.id.textView_ShowNum); mButton_IncreaseVal = (Button) findViewById(R.id.button_IncreaseNum); mEditText_SetNum = (EditText) findViewById(R.id.editText_SetNum); mButton_SetEditTextVal = (Button) findViewById(R.id.button_SetEditTextVal); mTextViewSomeText = (TextView) findViewById(R.id.someText); } } 

Presenter:

  public class MainPresenterImpl implements MainPresenter, Serializable { private static final String TAG = "MainPresenterImpl"; private MainView mMainView; private ExperimentObject mValueObject = new ExperimentObject(0); public MainPresenterImpl(MainActivity mainActivity) { mMainView = mainActivity; } @Override public void onCreate() { } @Override public void onResume() { } @Override public void setNewViewObj(MainView newViewObj) { mMainView = newViewObj; mMainView.setTextTextView(Integer.toString(mValueObject.getValue())); } @Override public void executeClickIncreaseBtn() { mValueObject.setValue( mValueObject.getValue() + 1 ); mMainView.setTextTextView(Integer.toString(mValueObject.getValue())); } @Override public void executeClickSetValBtn() { String valueStr = mMainView.getTextEditText().toString(); int value = Integer.parseInt(valueStr); mValueObject.setValue(value); mMainView.setTextTextView(valueStr); } } 
  • as far as I know the onDestroy call onDestroy not guaranteed, use onStop - ermak0ff
  • @ ermak0ff, thank you, yes, I agree with you. onStop is called guaranteed. - foxis
  • one
    You yourself write that there are not enough resources, so the phone unloads them from memory. In this case, the presenter does not save - pavel163
  • @ pavel163, but you cannot save it in a file. I've tried (described in the question), but so far to no avail. Maybe I'm doing something wrong. - foxis
  • one
    You also have a MainView here. This is an activation, and the activation is not serializable. Presenter also means not being serialized - pavel163

1 answer 1

The problem of non-seralizability Presenter was connected with the fact that the view object is not serializable (thanks a lot for the hint, @ pavel163 ). Having designated it as transient , my Presenter finally began to persist under any circumstances.

Activity remains the same, I will not bring it. And the Presenter changed the MainView field had to be made static, otherwise the listeners will refer to the old Presenter in which the MainView = null object MainView = null that will MainView = null error when using it.

As a result, the Presenter turned out like this:

 public class MainPresenterImpl implements MainPresenter, Serializable { private static final String TAG = "MainPresenterImpl"; private static transient MainView mMainView; private ExperimentObject mValueObject; public MainPresenterImpl(MainActivity mainActivity) { mMainView = mainActivity; mValueObject = new ExperimentObject(0); } @Override public void onCreate() { } @Override public void onResume() { } @Override public void setNewViewObj(MainActivity newViewObj) { Log.d(TAG, "setNewViewObj"); mMainView = newViewObj; mMainView.setTextTextView(Integer.toString(mValueObject.getValue())); } @Override public void executeClickIncreaseBtn() { mValueObject.setValue( mValueObject.getValue() + 1 ); mMainView.setTextTextView(Integer.toString(mValueObject.getValue())); } @Override public void executeClickSetValBtn() { String valueStr = mMainView.getTextEditText().toString(); int value = Integer.parseInt(valueStr); mValueObject.setValue(value); mMainView.setTextTextView(valueStr); } }