Android Handler changes WeakReference

My static handler has a WeakReference for my Activity (this is necessary to prevent a problem with documented memory).

I am sending a message with a long delay and I want this message to reach my activity (which should be in the foreground).

My concern is that when the orientation changes, my activity is destroyed, and the handler refers to the old activity that was supposed to be destroyed.

To get around this in my onCreate for activity, I do this.

  if(mHandler == null) mHandler = new LoginHandler(this); else { mHandler.setTarget(this); } 

And my handler is declared as a static global variable:

 private static LoginHandler mHandler = null; 

and the implementation class is also static, as shown below:

 private static class LoginHandler extends Handler { private WeakReference<LoginActivity> mTarget; LoginHandler(LoginActivity target) { mTarget = new WeakReference<LoginActivity>(target); } public void setTarget(LoginActivity target) { mTarget = new WeakReference<LoginActivity>(target); } @Override public void handleMessage(Message msg) { // process incoming messages here LoginActivity activity = mTarget.get(); switch (msg.what) { case Constants.SUCCESS: activity.doSomething(); break; default: activity.setStatusMessage("failed " + msg.obj, STATUS_TYPE_DONE); } } } 

What do I want to know if something is wrong with changing WeakReference to onCreate or something else is wrong with this approach?

Thanks,

+6
source share
2 answers

So, I wrote the following test to find out if I have the right idea or not, and it seems that m is right. In onCreate we change the WeakReference , and the sent message will always be delivered to the action, which is in the foreground. If you change this code to always create a new handler in onCreate , you will notice that update messages are not delivered.

 public class MainActivity extends Activity { private static int COUNT = 0; static LoginHandler mHandler; private static class LoginHandler extends Handler { private WeakReference<MainActivity> mTarget; LoginHandler(MainActivity target) { mTarget = new WeakReference<MainActivity>(target); } public void setTarget(MainActivity target) { mTarget.clear(); mTarget = new WeakReference<MainActivity>(target); } @Override public void handleMessage(Message msg) { // int duration = Toast.LENGTH_LONG; // process incoming messages here MainActivity activity = mTarget.get(); activity.update(msg.arg1); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if(mHandler == null) mHandler = new LoginHandler(this); else mHandler.setTarget(this); ((Button)findViewById(R.id.button)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Message msg = new Message(); msg.arg1 = COUNT++; mHandler.sendMessageDelayed(msg, 3000); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private void update(int count) { ((TextView) findViewById(R.id.hello_world)).setText("Hello World @ "+ count); } } 
+5
source

The solution to get away with the destruction and activity creation life cycle if you want to keep active objects is to use "Retent Fragments".

The idea is simple, you tell the Android system to "save" your fragment when the activity associated with it is destroyed and recreated. And make sure you capture the current activity context in the onAttach () fragment with the callable, so you always update the correct activity.

Below is more detailed information: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

0
source

Source: https://habr.com/ru/post/951682/


All Articles