【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )(二)

简介: 【Android】Handler 机制 ( Handler | Message | Looper | MessageQueue )(二)

V . Looper 子线程


1 . Looper 线程就是在普通线程的基础是哪个 , 加入了 Looper 用于消息调度 , 然后将消息转发给 Handler 进行处理 , 这样就实现了 在其它线程中 , 将任务异步分配给该 Looper 线程 ;



2 . Android 中的主线程本身就是 Looper 线程 , 整个 Looper 循环遍历消息的过程由系统完成 , 用户只需要自定义一个 Handler 成员 , 即可在子线程中调用该 Handler 将消息发送到主线程 , 在主线程执行相关操作 , 实现了将异步任务分配给主线程 , 这是子线程刷新 UI 的重要途径 ;




3 . 普通子线程 转为 Looper 子线程 流程 :



① 定义 Handler 成员变量 : 在线程 Thread 派生类中 , 定义 Handler 类型的成员变量 ;


② Looper 初始化 : 调用 Looper.prepare() 静态方法 , 该方法的作用是创建 Looper 变量 , 存储在了 ThreadLocal 中 , 将当前普通线程转为 Looper 线程 ;


③ 实例化 Handler 成员 : 一定要在 Looper.prepare() 之后实例化成员 , 因为如果在之前实例化 , Handler 与 Looper 无法产生关联 ;


④ 轮询消息队列 : 调用 Looper.loop() 方法 , 轮询消息队列 ( MessageQueue ) ;




4 . 实例化 Handler 成员时机 :



① 实例化时机 : 必须要在调用 Looper.prepare() 之后实例化才可以 , 因为实例化 Handler 对象时 , 会获取当前线程的 Looper , 如果为空 , 直接抛异常 ;


② Looper 对象创建 : Looper.prepare() 的作用就是创建 Looper 对象 , 将其放入 ThreadLocal 对象中存储 , 保证线程有且只有一个 Looper 对象 ;


public class handler {
  ...
  //获取 Looper 对象后 , 可以从 Looper 对象中获取 MessageQueue
  //关联后 , Handler 发送消息时 , 才能将消息精准的发送给
  final MessageQueue mQueue;
  //Handler 需要与线程的唯一 Looper 对象关联
    final Looper mLooper;  
    ...
    public Handler() {
      ...
  mLooper = Looper.myLooper()
  if (mLooper == null) {
    throw new RuntimeException(
    "Can't create handler inside thread that has not called Looper.prepare()");
  }
  ...
  mQueue = mLooper.mQueue;
  ...
  }
  ...
}



5 . 普通子线程 转为 Looper 子线程 代码示例 :



package kim.hsl.handler;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
/**
 * 将普通线程转为 Looper 线程
 *
 * 1. 定义 Handler 成员 ( 可以定义若干个 )
 * 2. Looper.prepare()
 * 3. 实例化 Handler 成员
 * 4. Looper.loop()
 *
 * @author hsl
 */
public class LooperThread extends Thread {
    /**
     * 1. 定义时不要实例化
     * Handler 实例化需要关联 Looper 对象
     * Looper 对象在 Looper
     */
    private Handler handler;
    @Override
    public void run() {
        super.run();
        //2. 将线程转为 Looper 线程
        //主要是创建 Looper 放入 ThreadLocal 对象中
        Looper.prepare();
        //3. 创建 Handler 必须在 Looper.prepare() 之后, 否则会崩溃
        handler = new Handler(){
            @Override
            public void handleMessage(@NonNull Message msg) {
                super.handleMessage(msg);
                //TODO 处理 Handler 相关业务逻辑
            }
        };
        //4. Looper 开始轮询 MessageQueue, 将消息调度给 Handler 处理
        Looper.loop();
    }
    public Handler getHandler() {
        return handler;
    }
    public void setHandler(Handler handler) {
        this.handler = handler;
    }
}




VI . Handler 发送 消息 种类


Handler 既可以发送静态的 消息 ( Message ) , 又可以发送动态的 操作 ( Runnable ) ;



当 Handler 所在的 Looper 线程接收到 消息 ( Message ) 时 , Looper 轮询到该 消息 ( Message ) 后 , 执行该消息对应的业务逻辑 , 这些逻辑一般都是在 Handler 中提前定义好的 ;


当 Handler 所在的 Looper 线程接收到 操作 ( Runnable ) 时 , Looper 轮询到该 操作 ( Runnable ) 后 , 直接运行该 Runnable 中的 run() 方法 ;






VII . Handler 机制总结


1 . Handler 机制运行流程 : Message 通过 Handler 发送给 Looper 线程的 MessageQueue , Looper 轮询 MessageQueue 将 Message 交给 Handler 执行 ;



2 . 线程异步调用 ( 作用 ) : 子线程刷新主线程 UI ( 子线程调用主线程 ) , 主线程调用子线程异步网络操作 ( 主线程调用子线程 ) ;



3 . 子线程转 Looper 线程 : ① 定义Handler 成员 ( 可以多个 ) , ② Loop.prepare() , ③ Handler 初始化 ( 必须在 prepare 之后 ) , ④ Looper.loop() ;



4 . 四组件关系 : 1 11线程 ⇔ \Leftrightarrow⇔ 1 11 Looper ⇔ \Leftrightarrow⇔ 1 11 MessageQueue ⇔ \Leftrightarrow⇔ n nn Handler ⇔ \Leftrightarrow⇔ m mm Message ;


目录
相关文章
|
1月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
38 2
|
24天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
27天前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
47 1
|
1月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
45 2
|
Android开发 安全
Android应用内广播LocalBroadcastManager机制详解
终于建了一个自己个人小站:https://huangtianyu.gitee.io,以后优先更新小站博客,欢迎进站,O(∩_∩)O~~ 1. 简介 通常我们在使用Android广播的时候都会直接将广播注册到系统的AMS当中,由于AMS任务繁忙,一般可能不会立即能处理到我们发出的广播,如果我们使用广播是在应用内的单个进程中使用,则完全可以采用LocalBroadcastManager来处理。
1302 0
|
5天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
7天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
9天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。
|
7天前
|
存储 API 开发工具
探索安卓开发:从基础到进阶
【10月更文挑战第37天】在这篇文章中,我们将一起探索安卓开发的奥秘。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和建议。我们将从安卓开发的基础开始,逐步深入到更复杂的主题,如自定义组件、性能优化等。最后,我们将通过一个代码示例来展示如何实现一个简单的安卓应用。让我们一起开始吧!
|
8天前
|
存储 XML JSON
探索安卓开发:从新手到专家的旅程
【10月更文挑战第36天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从零基础开始,逐步深入安卓开发的奥秘。无论你是编程新手,还是希望扩展技能的老手,这里都有适合你的知识宝藏等待发掘。通过实际的代码示例和深入浅出的解释,我们将解锁安卓开发的关键技能,让你能够构建自己的应用程序,甚至贡献于开源社区。准备好了吗?让我们开始吧!
21 2