• 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的地方

  • 相关阅读:
    多表联合查询,利用 concat 模糊搜索
    order by 中利用 case when 排序
    Quartz.NET 3.0.7 + MySql 动态调度作业+动态切换版本+多作业引用同一程序集不同版本+持久化+集群(一)
    ASP.NET Core 2.2 基础知识(十八) 托管和部署 概述
    ASP.NET Core 2.2 基础知识(十七) SignalR 一个极其简陋的聊天室
    ASP.NET Core 2.2 基础知识(十六) SignalR 概述
    ASP.NET Core 2.2 基础知识(十五) Swagger
    ASP.NET Core 2.2 基础知识(十四) WebAPI Action返回类型(未完待续)
    linux磁盘管理 磁盘查看操作
    linux磁盘管理 文件挂载
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5267260.html
Copyright © 2020-2023  润新知