关于Handler

handler类允许你发送消息和处理线程消息队列中的消息及runnable对象。handler实例都是与一个线程和该线程的消息队列一起使用,一旦创建了一个新的handler实例,系统就把该实例与一个线程和该线程的消息队列捆绑起来,这将可以发送消息和runnable对象给该消息队列,并在消息队列出口处处理它们。

handler类有两种主要用途:1按照时间计划,在未来某时刻,对处理一个消息或执行某个runnable实例。2把一个对另外线程对象的操作请求放入消息队列中,从而避免线程间冲突。

时间类消息通过如下方法使用post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable,long),sendEmptyMessage(int),sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long) methods. post之类函数可以传输一个runnable对象给消息队列,并在到达消息队列后被调用。sendmessage之类函数可以传送一个包含数据的message对象,该message对象可以被Handler类的handleMessage(Message) 方法所处理。

post之类函数和sendmessage之类的函数都可以指定消息的执行时机,是立即执行、稍后一段时间执行,还是在某个确定时刻执行。这可以用来实现超时、消息或其他时间相关的操作。

当一个进程启动时,主线程独立执行一个消息队列,该队列管理着应用顶层的对象(如:activitiesbroadcast receivers等等)和所有创建的窗口。你可以创建自己的一个线程,并通过handler来与主线程进行通信。这可以通过在新的线程中调用主线程的handlerpostsendmessage操作来实现。 

写的程序里类A中有一些操作比较耗时,就用了线程+handler,把耗时操作放到线程里执行,完成后handler发送消息,然后再更新UI

现在的问题是我在类里写的handler,总会提示一个警告:This Handler class should be static or leaks might occur

同一个线程下的handler共享一个looper对象,消息中保留了对handler的引用,只要有消息在队列中,那么handler便无法被回收,如果handler不是static那么使用HandlerServiceActivity就也无法被回收。这就可能导致内存泄露。当然这通常不会发生,除非你发送了一个延时很长的消息。

解决方案:Handler类应该为static类型,否则有可能造成泄露。在程序消息队列中排队的消息保持了对目标Handler类的应用。如果Handler是个内部类,那么它也会保持它所在的外部类的引用。为了避免泄露这个外部类,应该将Handler声明为static嵌套类,并且使用对外部类的弱应用。

 1.最不想动代码的同学,可以在Preference搜一下Lint,在Lint Error Checking里搜HandlerLeak,然后选择ignore,然后整个世界清净了。。。。(不推荐)

 2.上面的方法虽然简单,但是肯定不好的。。。给这个检查肯定是有用的,那第二种方法,自然就是把Handler定义成static,然后用post方法把Runnable对象传送到主线程:例。

                private static Handler handler;

                public void onCreate(Bundle savedInstanceState) {

                        super.onCreate(savedInstanceState);

                    setContentView(R.layout.main); // Create a handler to update the UI

                        handler = new Handler();

                }

                void test() {

                        handler.post(new MyRunnable());// 这样的方法同样可以用 SmsPopupActivity.this.runOnUiThread(new MyRunnalble());来替换,效果是一样的。

                }

                static public class MyRunnable implements Runnable {

                        @Override

                        public void run() {

                                imageView.setImageBitmap(downloadBitmap);

                                dialog.dismiss();

                        }

                } 

 3.看到这种方式可能又有很多人不乐意了,原来我一个handler处理多个消息,多舒服,你现在要我把每个消息都换成对应的Runnable对象发送,多不爽。

那我们可以通过弱引用的方式来做,例子如下示:我们首先定义了一个staticinner Class MyHandler然后让它持有Activity的弱引用。这样lint warning就消失了。

        static class MyHandler extends Handler {

                WeakReference<PopupActivity> mActivity;

                MyHandler(PopupActivity activity) {

                        mActivity = new WeakReference<PopupActivity>(activity);

                }

                @Override

                public void handleMessage(Message msg) {

                        PopupActivity theActivity = mActivity.get();

                        switch (msg.what) {

                        case 0:

                                theActivity.popPlay.setChecked(true);

                                break;

                        }

                }

        };

        MyHandler ttsHandler = new MyHandler(this);

        private Cursor mCursor;

        private void test() {

                ttsHandler.sendEmptyMessage(0);

        }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值