Android中的Handler

1、Handler在develpoer上的描述:

这里写图片描述
大致翻译:
一个Handler允许你发送和处理和这个进程相关联的消息队列中的消息和Runnable对象。每个Handler实例都与一个单独的线程关联并且在该线程的消息队列中。当创建一个新的处理程序,它是绑定到创建它的线程的线程/消息队列,从这一点上,它将传递消息和runnable对象,消息队列和执行他们出来的消息队列。

2、Handler有两个主要用途:

(1)更新ui
(2)发送消息,处理消息。

3、Handler常用方法:

1、post类方法允许你排列一个Runnable对象到主线程队列中

post(Runnable)
postDelayed(Runnable long)
2、sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新。
sendEmptyMessage(int)
sendMessage(Message)
sendMessageDelayed(Message,long)

4、android中为什么只能通过Handler更新UI。

根本目的:解决多线程并发产生更新UI错误的情况。

如果在一个activity中有多个线程更新UI,并且没有任何管理机制,会产生更新UI界面错乱的情况。因此为了避免这样的情况:android提供了handler这样一套机制让我们更新UI,我们也就不用考虑多线程下的更新UI问题,所有的更新UI操作,都是在主线程的消息队列中去轮询处理。

5、Handler的原理:

这里写图片描述

1、Looper:内部包含一个消息队列MessageQueue,所有的Handler发送的消息都到这个消息队列中。
Looper.looper方法,是一个死循环,不断的从MessageQueue中取出消息,如果有消息就取出消息。


2、MessageQueue是一个消息队列,可以添加消息,也可以处理消息。


3、Handler负责发送消息和接收传递过来的消息,从而更新UI。

6、用handler实现计时器

public class MainActivity extends Activity {
    private MyHandler handler;
    private int a = 0;
    private TextView tv_time;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_time = (TextView) findViewById(R.id.tv_time);
        handler = new MyHandler();
        new Thread() {
            public void run() {
                handler.postDelayed(this, 1000);
                a++;
                tv_time.setText(a + "");
                // handler.sendEmptyMessage(1);
            };
        }.start();

    }

    class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            // 处理不同的消息信息;
            // switch (msg.what) {
            // case 1:
            // tv_time.setText("这是1传来的");
            // break;
            //
            // case 2:
            // tv_time.setText("这是2传来的");
            // break;
            // }
            super.handleMessage(msg);
        }
    }

}

7、发送handler所携带的消息。

Message msg = new Message();
1、msg.what = 0; (值随意定义,和handlemessage 匹配就可以)
2、msg.agr1,2在handler中从msg中取出(arg1,arge可以携带两个参数);
3、msg.obj:可以传递一个对象。

 class Person {
         public String name;
         public int age;
     }
         Message message=new Message();
         Person p=new Person();
         p.name="张三";
         p.age=24;
         message.obj=p;
         handler.sendMessage(message);

8、handler引起的内存泄露问题

当使用内部类(包括匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类对象(通常是一个Activity)的引用(不然你怎么可能通过Handler来操作Activity中的View?)。而Handler通常会伴随着一个耗时的后台线程(例如从网络拉取图片)一起出现,这个后台线程在任务执行完毕(例如图片下载完毕)之后,通过消息机制通知Handler,然后Handler把图片更新到界面。然而,如果用户在网络请求过程中关闭了Activity,正常情况下,Activity不再被使用,它就有可能在GC检查时被回收掉,但由于这时线程尚未执行完,而该线程持有Handler的引用(不然它怎么发消息给Handler?),这个Handler又持有Activity的引用,就导致该Activity无法被回收(即内存泄露),直到网络请求结束(例如图片下载完毕)。另外,如果你执行了Handler的postDelayed()方法,该方法会将你的Handler装入一个Message,并把这条Message推到MessageQueue中,那么在你设定的delay到达之前,会有一条MessageQueue -> Message -> Handler -> Activity的链,导致你的Activity被持有引用而无法被回收。

解决办法:
方法1、在activity销毁的时候结束后台线程
方法2、将Handler声明为静态类。

static class MyHandler extends Handler {
    WeakReference<Activity > mActivityReference;

    MyHandler(Activity activity) {
        mActivityReference= new WeakReference<Activity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
        final Activity activity = mActivityReference.get();
        if (activity != null) {
            mImageView.setImageBitmap(mBitmap);
        }
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值