Android 知识点分享

Handler机制整理

2017-07-21  本文已影响78人  杨充211

Handler机制整理
目录介绍
1.关于handler消息机制图
2.关于handler基本介绍
3.使用handler的几种方法
4.关于handler底层源码解读

1.关于Handler消息机制图

Image.png

2.关于Handler机制基本解读
Message
消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

sendMessage(message);                                    //发送消息
sendEmptyMessage(0);                                     //其实内部实现还是和上面一样
endEmptyMessageAtTime(int what, long uptimeMillis);      //定时发送空消息
sendEmptyMessageDelayed(int what, long delayMillis);     //延时发送空消息
sendMessageAtTime(Message msg, long uptimeMillis);       //定时发送消息
sendMessageDelayed(Message msg, long delayMillis);       //延时发送消息
sendMessageAtFrontOfQueue(Message msg);                  //最先处理消息(慎用)

Handler
处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue
消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
把消息进行排序,排序的依据就是消息要执行的时间

Looper
消息泵,不断地从MessageQueue中抽取Message执行。通过Looper去消息队列取消息
当主线程创建的时候,就会创建一个looper,looper在new的时候会创建一个MessageQueue 。所以,一个线程对应一个Looper一个Looper对应一个MessageQueue
Looper创建之后必须调用loop方法,loop方法中有一个死循环,这个死循环会不断去消息队列里取消息,取出消息之后就会调用handler的handlemessage方法处理消息

Thread
线程,负责调度整个消息循环,即消息循环的执行场所。

3.使用handler的几种方法
1.1主线程中定义Handler,子线程中发消息,通知Handler完成UI更新
Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用

在主线程中

主线程接收消息处理操作
private Handler myHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch(msg.what) {
            case 0:
                //更新UI等
                break;
            case 1:
                //更新UI等
                break;
            default:
                break;
        }
    }
};
//开启一个子线程,子线程发送信息
new Thread(
        new Runnable() {
            @Override
            public void run() {
                //处理耗时逻辑
                if(a==1){               //直接发送信息,消息标识中并没有带参数
                    /**
                     *获取消息,尽量用obtainMessage()方法,查看源码发现,该方法节省内存。
                     *不提倡用Messenger msg=new Messenger()这种方法,每次创建一个对象,肯定不节省内存啦!
                     *至于为什么该方法还存在,估计还是有存在的必要吧。(留作以后深入研究)
                     */
                    Message message = myHandler.obtainMessage();
                    message.what = 1;                               //消息标识
                    myHandler.sendMessage(message);                 //发送消息
                }else if(a==2){
                    Message msg = myHandler.obtainMessage();
                    msg.what = 1;                                   //消息标识
                    msg.arg1=2; //存放整形数据,如果携带数据简单,优先使用arg1和arg2,比Bundle节省内存。
                    msg.arg2=3;                                     //存放整形数据
                    Bundle bundle=new Bundle();
                    bundle.putString("dd","abcd");
                    bundle.putInt("love",5);
                    msg.setData(bundle);
                    msg.obj=bundle;                                 //用来存放Object类型的任意对象
                    myHandler.sendMessage(msg);                     //发送消息
                }else if(a==3){
                    Message obtain = Message.obtain();
                    obtain.what = 1;
                    myHandler.sendMessage(obtain);
                }else if(a==4){
                    myHandler.sendEmptyMessage(0);                  //其实内部实现还是和上面一样
                }
            }
        }
).start();

2.1用Activity对象的runOnUiThread方法更新

new Thread() { 
    public void run() { 
    //这儿是耗时操作,完成之后更新UI; 
    runOnUiThread(new Runnable(){ 
        @Override 
        public void run() { 
        //更新UI 
        } 
    }); 
    } 
}.start(); 
如果在非上下文类中(Activity),可以通过传递上下文实现调用;
Activity activity = (Activity) imageView.getContext(); 
activity.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
    //更新UI 
    imageView.setImageBitmap(bitmap); 
    } 

4.关于handler底层源码解读

上一篇下一篇

猜你喜欢

热点阅读