Handler机制整理

作者: 杨充211 | 来源:发表于2017-07-21 21:31 被阅读78次

    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底层源码解读

    相关文章

      网友评论

        本文标题:Handler机制整理

        本文链接:https://www.haomeiwen.com/subject/ccqykxtx.html