zoukankan      html  css  js  c++  java
  • Looper、Hander、HandlerThread

    一.Message 、Looper、Handler之间的关系

    1.系统发送的Message消息传送给Handler,Handler将Message放入自己的looper队列的底部
       然后再从Looper的顶部获取Message信息,并执行方法。

    2.一个Handler只有一个Looper,一个Message仅与一个Handler交互,多个Handler可以与一个Looper交互。

    3.主线程自带Hanlder和Looper

    4.小技巧:为避免创建Message对象,所以调用Handler.obtainMessage()方法从公共池中获取Message,发送message:message.sendToTarget()。

    //假设已经有一个Handler
    mHandler.obtainMessage(int what,Obj obj)
                    .sendToTarget();

    Message的解剖

    Message最重要的三个变量:

    what:用来描述信息,相当于Map的键值对的键。//因为有很多message发送给Handler所以Handler需要分辨

    obj:存储对象,相当于Map的键值对的值。//Msg发送给Handler的对象

    target:处理消息的Handler

    arg1,arg2:存储数字,准备用来发送给Handler

    Message在准备处理状态下,Handler负责处理行为。

    :通常对Message对象不是直接new出来的,只要调用handler中的obtainMessage方法来直接获得Message对象。

    Looper的解剖

    1.Looper的作用:是负责管理消息队列,负责消息的出列和入列操作。

    2.流程:系统发送的Message消息传送给Handler,Handler将Message放入自己的looper队列的底部,然后再从Looper的顶部获取Message信息。

    一个Handler只有一个Looper,多个Handler可以与一个Looper交互。

    3.Looper的使用:Looper.myLooper():获取当前进程的looper对象,类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。 

                                    Looper.prepare():创建Looper(主线程自带Looper,在子线程中使用创建Looper)

                                    Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。 

                           注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。 

    Handler的解剖

    1.Handler主要有两个用途:首先是可以定时处理或者分发消息,其次是可以添加一个执行的行为在其它线程中执行

    2.使用:子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据。

    创建Handler的三种方法
    //直接创建匿名类 缺点:默认为主进程的Looper Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) {//覆盖handleMessage方法 switch (msg.what) {//根据收到的消息的what类型处理 case BUMP_MSG: Log.v("handler", "Handler===="+msg.arg1);//打印收到的消息 break; default: super.handleMessage(msg);//这里最好对不需要或者不关心的消息抛给父类,避免丢失消息 break; } } //用new Handler(Looper looper,CallBack) Handler myHandler = new Handler(new Callback(){ // 参数也可以为(this.getMainLooper(),new Callback(){})不写则默认为主线程的Looper,如果是在子线程中创建,Looper默认为子线程的Looper
    //Handler不带参数的默认构造函数:new Handler(),实际上是通过Looper.myLooper()来获取当前线程中的消息循环,详见3
    @Override public boolean handleMessage(Message msg) { // TODO Auto-generated method stub return false; } }); //子类继承Handler class MyHandler extends Handler { public MyHandler() { } //默认为主线程的Looper public MyHandler(Looper L) { super(L); } //自定义的Looper // 子类必须重写此方法,接受数据 @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub Log。d("MyHandler""handleMessage。。。。。。"); super。handleMessage(msg); // 此处可以更新UI Bundle b = msg。getData(); String color = b。getString("color"); MyHandlerActivity。this。button。append(color); } }


    3.在非主线程中Looper与Handler和Thread

    在非主线程中直接new Handler() 错误,原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。

    默认情况下,线程是没有消息循环的,所以要调用 Looper.prepare()来给线程创建消息循环,然后再通过,Looper.loop()来使消息循环起作用。 

    class LooperThread extends Thread
    
    {
          public Handler mHandler;
    
          public void run() 
    
          {
    
                 Looper.prepare();
    
                 mHandler = new Handler() 
    
                 {
    
                          public void handleMessage(Message msg) 
    
                         {
    
                                 // process incoming messages here
    
                         }
    
                 };
                Looper.loop();
          }
    }

    作用可实现主线程给子线程(非主线程)发送消息

    :UI最好只能在主线程中运行。

    二、HandlerThread

    简介:继承自Thread,线程同时创建了一个含有消息队列的Looper,并对外提供自己这个Looper对象的get方法,这就是它和普通Thread唯一不同的地方。

    使用

    1. 创建一个HandlerThread,即创建了一个包含Looper的线程。

      HandlerThread handlerThread = new HandlerThread("leochin.com");

      handlerThread.start(); //创建HandlerThread后一定要记得start()

    2. 获取HandlerThread的Looper(getLooper()是在start()之后使用的)

      Looper looper = handlerThread.getLooper();

    3. 创建Handler,通过Looper初始化

      Handler handler = new Handler(looper); 

    通过以上三步我们就成功创建HandlerThread。通过handler发送消息,就会在子线程中执行。

     4.  关闭HandlerThread

    handlerThread.quit();

    子类继承HandlerThread时创建的小技巧:

    class MyHandlerThread extends HandlerThread {
          public MyHandlerThread(String name) {
              super(name);
          }//一定要定义当前Thread的名字
    }

    2.onLooperPrepare()是最适合创建内部Handler的地方

  • 相关阅读:
    svn使用
    navicat 15 安装破解
    thinkpad交换Fn和Ctrl
    emqx_mqtt安装+mqtt管理工具
    Adobe XD使用
    FolderPainter:windows系统为文件夹设置不同颜色
    rest client 代替postman
    使用bfg快速清理git历史大文件
    Adobe Acrobat XI Pro v11.0.10中文版
    Excel 2016打开文档时提示“操作系统当前的配置不能运行此应用程序”
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5267260.html
Copyright © 2011-2022 走看看