Handler的使用小结

Android UI的控件都不是线程安全的,如果允许并发访问,那控件的状态就是未知;所以Android只允许在 一个线程内对UI控件进行更新,这个线程就是创建View时的线程,默认状态下,这个线程就是主线程,这也就是为什么我们在对UI组件进行更新的时候,必须回到主线程去通过Handler操作。

在使用Handler的时候,有时候处理不当就会导致内存泄露, 当我们试图使用内部类或者匿名内部类重写Handler的handlerMessage()方法,一定要保证他们是静态,因为内部类和匿名内部类默认都会 持有外部类的引用,我们上面已经分析过,handler发送的每条Message都会持有一个对发送者的引用,即对handler的引用,如果我们发送了 延迟消息,直到我们关掉Activity的时候,消息还在消息队列里,就会发生内存泄露,引用链是这样的:
messageQueue->message->handler->activity

解决方案就是把内部类或者匿名内部类分别设置成静态内部类和静态成员,这样就没有没有了对外部activity的引用,如果需要对外部 Activity的引用可以给handler添加一个队外部类的弱引用。当然从上面的引用关系中,我们还可以有另外一种解决方案,那就是在退出的时候清空 消息队列,这样也可以达到我们的目的。

解决方案一: onDestroy时清除消息,mHandler.removeCallbacksAndMessages(null); // 参数为null时会清除所有消息。

解决方案二:声明Handler为static并持有Activity的弱引用。关键看程序中注释的地方

public class MainActivity extends Activity {

    private static final String tag = "MainActivity";

    private TextView mTvShow;

    private MyHandler mHandler;

    private static final int DELAY_TIME = 10000; // set to 5s and 10s to check result.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHandler = new MyHandler(MainActivity.this);

        Log.e(tag, "onCreate");

        mTvShow = (TextView)findViewById(R.id.tv_show);

        new Thread() {
            @Override
            public void run() {

                mHandler.sendEmptyMessageDelayed(1, DELAY_TIME);
                Log.e(tag, "msg send");
            }
        }.start();

    }

    @Override
    protected void onDestroy() {
        Log.e(tag, "onDestroy");
        super.onDestroy();
    }

    static class MyHandler extends Handler{

        WeakReference<mainactivity> mWeakActivity;

        public MyHandler(MainActivity activity) {
            mWeakActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            MainActivity activity = mWeakActivity.get();

            Log.e(tag, "handleMessage," + msg.what);
            // 5s is not null, 10s is null, tell that activity is recycled.
            if(null == activity){
                Log.e(tag, "null");
            }else{
                Log.e(tag, "not null");
                activity.mTvShow.setText("delay show");
            }
        }
    }
}//mainactivity
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安德路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值