Handler

作者: 沅兮 | 来源:发表于2017-07-13 13:55 被阅读0次

    Handler初步

    Handler是什么?
    • Handler是Android给我们提供用来更新UI的一套机制,也是一套消息处理的机制,我们可以发送消息,也可以通过它处理消息。
    为什么要用Handler?
    • Android在设计的时候,就封装了一套消息创建.传递.处理机制,如果不遵循这样的机制就没法更新UI信息的,就会抛出异常信息.
    使用Handler遇到的问题?
    • 子线程中存在实例化Handler时必须要使用Looper,否则会出错。
    实现一个与线程相关的Handler
    • 就是在线程Thread中声明Handler,其他地方都是主线程,所以不要在主线程中的handler中做耗时操作。
    子线程和主线程互发消息
    • 主线程给子线程发送:threadHandler.sendMessage();
    • 子线程给主线程发送:mainHandler.sendmessage();
    Andorid更新UI的几种方式
    • runOnUiThread(Runnable)
    • view.post(Runnable)
    • handler sendMessage
    • handler.post(Runnable)
    非UI线程更新View
    • 某些时候可以,但是不推荐使用;在onCreate()中使用子线程更新UI,但是不使用延时就可以了,因为检测当前线程是否是在onResume()中完成的。

    Handler标准写法

    • Handler的标准写法,避免的内存泄漏
    • 内存泄漏:内部类会自动引用外部类,当Activity销毁时,handler如果正在运行,那么activity其实并没有真正的销毁,会造成内存泄漏 -- 在onDestroy()中将handler制为空
    private final MyHandler handler = new MyHandler(this);
    
    private static class MyHandler extends Handler {
       /**
        * 此处使用弱引用
        *   强引用:new出来的对象,内存不够也不会销毁
        *   软引用:内存不够才会销毁
        *   弱引用:引用对象不存在就销毁
        */
        private final WeakReference<Test1Activity> weakReference; --> 可以是View
        public MyHandler(Test1Activity activity) {
        weakReference = new WeakReference<Test1Activity>(activity); 
     }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Test1Activity activity = weakReference.get();
                if (activity != null) {
                    // 使用Activity对象访问外部对象
                    activity.textView.setText("你好呀!");
                }    
            }
        }~~~
    
    
    # Handler怎么使用?
    

    sendMessage、sendMessageDelayed

    Messagemessage = handler.obtainMessage(what, arg1, arg2,obj);
    // sendToTarget()方法与sendMessage()方法功能一样,Target就是handler,是封装好的一个方法
    message.sendToTarget();
    handler.sendMessage(message);~~~

     3.post(Runnable) --> 调用在Runnable中更新UI
    // 调用Runnable
    handler.post(runnable);
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            index++;
            index = index % 3;
            image.setImageResource(img[index]);
            handler.postDelayed(runnable, 500);
        }
    };~~~
    

    postDelayed(Runnable,long) 在Runnable中更新 --> 通过handler.post等调用runnable

    new Handler(new CallBack()) --> 可以截取handler发送的消息

    handler.removeCallbacks(Runnable) --> 移除runnable,结束handler的操作

    Handler handler = new Handler(new Callback() {
    // Callback()是截取handler发送的消息,当返回值为false时,获得消息,原来的handleMessage()可以获得消息;
    // 当返回值为true时,截取消息,原来的handleMessage()收不到消息
    // 上面的handleMessage()是 new Callback()中的方法
    // 下面的handleMessage()是 new Handler()中的方法
    @Override
    public boolean handleMessage(Message msg) {
    Toast.makeText(Img2Activity.this, "1", Toast.LENGTH_SHORT).show();
    return true;
    }
    }) {
    public void handleMessage(Message msg) {
    Toast.makeText(Img2Activity.this, "2", Toast.LENGTH_SHORT).show();
    };
    };~~~

    Android为什么设计只能通过Handler机制更新UI呢?
    • 最根本的目的就是解决多线程并发问题.
    • 假设如果在一个Activity当中,有多个线程去更新UI,并且都没有加锁机制,会出现什么问题?--> 更新界面错乱
    • 如果对更新UI的操作都进行加锁处理的话又会产生什么样的问题?--> 性能下降
    • 总结:不用关心多线程的问题,所有的更新UI的操作,都在主线程的消息队列当中去轮询处理.

    Handler原理

    • Handler封装了消息的发送(主要包括消息发送给谁)
    • Looper内部包含一个消息队列也就是MessageQueue,所有的Handler发送的消息都走向这个队列。Looper.Looper方法,就是一个死循环,不断的从MessageQueue取消息,如有消息就处理消息,没有消息就阻塞
    • MessageQueue,就是一个消息队列,可以添加消息,并处理消息Handler内部会跟Looper进行关联,也就是说Handler的内部可以找到Looper,找到了Looper也就找到了MessageQueue,在Handler中发送消息,其实就是向 MessageQueue队列发送消息。MessageQueue是先进先出原则
    • handler负责发送消息,Looper负责接受Handler发送的消息,并直接把消息回传给Handler自己,MessageQueue就是一个存储消息的容器
    • 主线程创建时,同时也会创建MessageQueue和Looper对象

    HandlerThread

    • 系统定义的一个继承自Thread的类,我们可以在实例化Handler中指定handlerThread.getLooper()这样的Looper名字,这样我们的Handler就变成了子线程的handler,就可以做耗时操作了.
    // 定义HandlerThread,是Thread的子类,就是一个线程
    HandlerThread handlerThread = new HandlerThread("child_child");
    // 启动线程
    handlerThread.start();
    // 此时的Handler就变成了子线程中的Handler,可以做一些耗时的操作
    // 默认的情况下,Handler是主线程中的Handler,不可以做耗时操作
    Handler handler = new Handler(handlerThread.getLooper()){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            // 在这里我们可以做一些耗时的操作
        }
    };~~~
    

    相关文章

      网友评论

          本文标题:Handler

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