Android中Handler的使用方法

Android中Handler的使用方法

几乎所有人第一次使用到Handler类的时候,都是因为想在非主线程更新UI,然后在更新UI的时候报错,才发现Handler的,现在来看一下网上的通用给法

public class HandlerActivity extends Activity {

private Handler mHandler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
        switch(msg.what){
            case 1:
            //更新UI
            break;

        }
        super.handleMessage(msg);
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new Thread(new Runnable() {
        @Override
        public void run() {
            Message msg=new Message();
            msg.what=1;
            mHandler.sendMessage(msg);
        }
    }).start();
}

}

我们通过新建一个Handler对象,然后在子线程中进行业务处理,当处理完成中再将信号通过mHandler发送到主线程中,Handler再收到消息后就会对其进行处理。在使用Android Studio的时候,细心的同学会发现,Handler中给出了警告提示:
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.
一旦Handler被声明为内部类,可能导致它的外部类不能被垃圾回收。如果Handler是在其他线程使用Looper或MessageQueue,而不是在UI线程,那么就没有这个问题。如果Handler使用Looper或MessageQueue在主线程(main thread),你需要修改你的Handler声明:
声明Handler为static类;在外部类中实例化一个外部类的WeakReference(弱引用)并且在Handler初始化时传入这个对象给你的Handler;将所有引用的外部类成员使用WeakReference对象。

出现这个问题的主要原因是,当结束Activity时由于外部对handler 有一个引用,而handler 持有Activity的引用,这样就导致了GC不会回收,引发内存泄露,GC的回收机制是,如果某个对象不再被引用,那么该对象将被回收。如 A a=new A(),此时就创建一个对象A,a去引用,但是如果我们将a=null;后,由于对象A不再被引用,对象A就会被回收。所以,如一些需要在对象销毁时才执行的函数,如Activity的onDestroy,由于Activity没有被回收,导致内存泄露 ,引发的并发问题onDestroy不能被执行,有时候当某个函数不能被正常调用时,应该考虑是否内存泄露引发的,其实这种问题在C/C++中经常出现,只是java 弱化了指针的概念(或者说没有指针这个东西),导致JAVA中对内存泄露不是特别重视。

说了这么多废话 该说一下如何解决了,根据这个警告提到的我们可以使用弱引用,来解决这个问题。使用静态内部类,通过WeakReference实现对Activity的弱引用,直接上代码:

public class HandlerActivity extends Activity {

private static class WeakReferenceHandler extends Handler{
    WeakReference<HandlerActivity> mActivity;
    private String TAG="StudentSocreHandler";
    public WeakReferenceHandler(HandlerActivity activity){
        mActivity=new WeakReference<>(activity);
    }
    @Override
    public void handleMessage(Message msg) {
        HandlerActivity mHandlerActivity=mActivity.get();
        switch (msg.what){
            case 1:
                //更新UI 通过mHandlerActivity得到Activity中的对象

                break;
        }
        super.handleMessage(msg);
    }
}
private WeakReferenceHandler mWeakReferenceHandler=new WeakReferenceHandler(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Work.WorkThread(mWeakReferenceHandler);
}
}


class Work{
        public static void WorkThread(final Handler mHandler){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Message msg=new Message();
                    msg.what=1;
                    mHandler.sendMessage(msg);
                }
            }).start();
        }
    }


WeakReference的作用就是将Activity进行弱引用,一旦Activity要被销毁时,由于Handler对Activity持有的引用是弱引用,此时,GC会及时回收Activity,防止内存泄露这就是使用弱引用的好处。但是并不是任何地方都能随便使用弱引用的,使用不当很容易造成空指针异常,所以需要合理的使用。

借鉴文章:
谈谈java中的WeakReference
Android实战技巧之三十八:Handler使用中可能引发的内存泄漏 该文章提到的另一种实现方法大家不防去试试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值