Android Handler changing WeakReference

▼魔方 西西 提交于 2019-12-18 12:06:10

问题


My static handler has a WeakReference to my Activity (this is to prevent the well documented memory leak issue).

I post a long delayed message and I want this message delivered to my activity (which should be in the foreground).

My concern is that on orientation change, my activity is destroyed and the handler has a reference to the old activity which should have been destroyed.

In order to get around this in my onCreate for the 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 implementing class is also static as 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 I want to know is if there is something wrong with changing the WeakReference on onCreate or is there anything else wrong with this approach?

Thanks,


回答1:


So I wrote the following test to figure out whether I had the right idea or not and it seems that m approach is correct. In onCreate we change the WeakReference and the posted message will always get delivered to the activity that is in the foreground. If you change this code to always create a new Handler in onCreate you'll notice the update messages do not get 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);
    }

}



回答2:


A solution in getting away with activity's destroy-and-create life cycle, if you want to retain the active objects is to make use of the "Retent Fragments".

The idea is simple, you are telling the Android system to " retain" your fragment, when it's associated activity is being destroyed and re created. And make sure you grab the current activity's context in the fragment's onAttach() callable, so you are always updating the correct activity.

Below link has more details: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html



来源:https://stackoverflow.com/questions/18221593/android-handler-changing-weakreference

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!