android – Presenter persistence in MVP while secretly destroying the application

Question:

In the application for Android, the following problem arose (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 Activity fields are erased, including my Presenter .

To save Presenter Tried using

1) onRetainCustomNonConfigurationInstance ,

2) static field for Presenter object

3) as well as a 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 the configuration (changing the screen orientation), all of the above methods work fine.

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

Is it possible in my case to somehow solve this situation? Ideally, you need to save the Presenter object so that when the application is destroyed, you can return it, a shared preference is well suited here, but it works only with primitive objects, in this case the presenter cannot be saved with it.


An attempt to save the Presenter to an external file was unsuccessful. Even though both Preseneter and ExperimentObject within 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);
}
}

Answer:

The problem of non-serializability of Presenter was related to the fact that the view object is not serializable (thanks a lot for the tip, @ pavel163 ). By designating it as transient , my Presenter finally started to persist under all circumstances.

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

As a result, the Presenter looks 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);
}


}
Scroll to Top