文章讲述Looper/MessageQueue/Handler/HandlerThread相关的技能和使用方法.

什么是Looper?Looper有什么作用?

Looper是用于给线程(Thread)添加消息队列(MessageQueue)的工具;让消息队列的处理处于循环状态,一旦接收到消息,会唤醒线程并执行消息处理方法.

通常情况下,Activity和Service等系统组件不会使用到Looper,Framework层已经为其初始化好了线程(附带有消息队列,称为主线程或UI线程);主线程会一直运行,处理用户事件.

如果我们需要新建一个线程,且这个线程要能够循环处理其他线程发过来的消息事件,或者需要长时间与其他线程进行交互,这时就需要使用到Looper给线程建立消息队列.

Looper怎么用?

Looper类中以下方法:

比较常用的是以下方法:

public static void prepare();
public static Looper myLooper();
public static void loop();
public void quit();

方法描述:

1. prepare():在线程run()最开始,调用该方法;为线程初始化消息队列.

2. myLooper():获取Looper对象引用;一定要在prepare()之后调用.

3. loop():让线程的消息队列开始运行,接收消息;

4. quit():退出消息循环.若线程中无其他操作,线程将终止运行.

    public class WorkThread extends Thread {
// 工作线程的Handler实例
private Handler mHandler;
// 工作线程的Looper实例
private Looper mLooper;
public WorkThread() {
LogUtil.d(TAG, "WorkThread::starting...");
start();
}
public void run() {
LogUtil.d(TAG, "WorkThread::runningF...");
// 初始化消息队列
Looper.prepare();
// 获取Looper对象
mLooper = Looper.myLooper();
// 在工作线程创建Handler
mHandler = new Handler(mLooper) {
@Override
public void handleMessage(android.os.Message msg) {
LogUtil.d(TAG, "handleMessage::starting...");
StringBuilder sb = new StringBuilder();
sb.append("it is my please to serve you, please be patient to wait!\n");
// 子线程一直在循环执行
for (int i = 0; i < 100; i++) {
sb.append(".");
Message newMsg = Message.obtain();
newMsg.obj = sb.toString();
mMainHanlder.sendMessage(newMsg);
SystemClock.sleep(1000);
}
sb.append("\nyour work is done");
Message otherMsg = Message.obtain();
otherMsg.obj = sb.toString();
mMainHanlder.sendMessage(otherMsg);
};
};
// 开始接收消息
Looper.loop();
}
public void exit() {
LogUtil.d(TAG, "exit::starting...");
if (mLooper != null) {
// 退出消息循环
mLooper.quit();
mLooper = null;
LogUtil.d(TAG, "exit::mLooper is set to null");
}
}
public void executeTask(String txt) {
LogUtil.d(TAG, "executeTask::starting...");
if (mLooper == null || mHandler == null) {
LogUtil.d(TAG, "executeTask::mLooper is null");
Message msg = Message.obtain();
msg.obj = "Sorry man, it is out of service";
// 使用主线程的Handler实例,向主线程发送Message
mMainHanlder.sendMessage(msg);
return;
}
LogUtil.d(TAG, "executeTask::mLooper is not null");
Message msg = Message.obtain();
msg.obj = txt;
mHandler.sendMessage(msg);
}
}

在工作线程中创建的Handler是属于该子线程(工作线程)的,而不是主线程.

疑惑:

Thread的状态和Looper的关系:未退出消息循环时,Thread是不会死亡的;一旦消息队列接收到消息,则会唤醒线程并处理消息.

何时退出Thread?如上述所说,若没有消息队列,一旦run()执行结束,该Thread也就是结束.

Handler是用于操作线程内部消息队列的类.即是用Handler来操作消息队列.如:给消息队列发送消息,和从消息队列中取出消息并处理.Handler作用:用于线程内部消息处理;用于线程间通讯(ITC-Inter Thread Communication).

必须要指出的是,此处的Handler来自于:import android.os.Handler;

Handler用于线程内部消息处理,即在将来定时执行某个动作,或者周期性执行动作.Handler用于操作线程内部的消息队列,可以用来线程间通信ITC,大大减少同步的烦恼,甚至不需要使用synchronized.

Handler/Looper/MessageQueue是属于一个线程内部的数据,但提供给外部线程访问的接口,Handler就是公开给外部线程,与线程通讯的接口.MessageQueue是相对较底层的,较少直接使用;Looper和Handler就是专门用来操作底层MessageQueue的.

Handler是用于操作一个线程内部的消息队列的,所以Handler必须依附于一个线程,而且只能是一个线程.也就是说:必须在一个线程内创建Handler,同时制定Handler的回调方法handlerMessage(Message msg).

以上方法都是设置定时器,在指定的时间向Handler所在的MessageQueue发送消息.线程内部消息循环并不是并发处理(并非创建一个线程),而是在同一个线程中处理.

并发执行或处理,既是多线程执行.

正确创建Handler,需要让Handler与线程绑定.如果给Handler指定Looper对象,此时Handler便绑定到Looper对象所在的线程.Handler的消息处理回调方法会在这个线程执行;如果不指定Looper,则Handler绑定到创建此Handler的线程内,消息处理回调方法也在这个线程执行.

如果要在一个线程中使用消息队列和Handler,Android API中有已经封装好的HanlderThread,在这个类中已经做好了Looper的初始化工作.

    private void initBackThread() {
mIndexUpdateThread = new HandlerThread("check-message-coming");
mIndexUpdateThread.start();
// 使用mIndexUpdateThread创建Handler实例,即这个Handler就在mIndexUpdateThread线程中
mIndexUpdateHandler = new Handler(mIndexUpdateThread.getLooper()) {
@Override
public void handleMessage(android.os.Message msg) {
int what = msg.what;
LogUtil.d(TAG, "handleMessage::msg.what=" + what
+ "; Thread name=" + Thread.currentThread().getName());
checkforUpdate();
if (mIsUpdateInfo) {
// 实现循环更新
mIndexUpdateHandler.sendEmptyMessageDelayed(
MSG_UPDATE_INFO, 500);
}
};
};
}

Handler Looper 解析的更多相关文章

  1. Android之消息机制Handler,Looper,Message解析

    PS:由于感冒原因,本篇写的有点没有主干,大家凑合看吧.. 学习内容: 1.MessageQueue,Looper,MessageQueue的作用. 2.子线程向主线程中发送消息 3.主线程向子线程中 ...

  2. Handler Looper源码解析(Android消息传递机制)

    Android的Handler类应该是常用到的,多用于线程间的通信,以及子线程发送消息通知UI线程刷新View等等.这里我主要总结下我对整个消息传递机制,包括Handler,Looper,Messag ...

  3. handler looper和messageQueue

    一.用法. Looper为了应付新闻周期,在创建过程中初始化MessageQueue. Handler在一个消息到当前线程的其他线程 MessageQueue用于存储所述消息 Looper其中线程创建 ...

  4. Handler+Looper+MessageQueue深入详解

    概述:Android中的异步处理机制由四部分组成:Handler+Looper+MessageQueue+message,用于实现线程间的通信. 用到的概念: Handler: 主要作用是发送消息和处 ...

  5. 讲讲Handler+Looper+MessageQueue 关系

    Handler+Looper+MessageQueue这三者的关系其实就是Android的消息机制.这块内容相比开发人员都不陌生,在面试中,或者日常开发中都会碰到,今天就来讲这三者的关系. 概述: H ...

  6. Android的消息机制: Message/MessageQueue/Handler/Looper

    概览   * Message:消息.消息里面可包含简单数据.Object和Bundle,还可以包含一个Runnable(实际上可看做回调). * MessageQueue:消息队列,供Looper线程 ...

  7. Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别?

    一个帖子的整理: Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别如果你不带参数的实例化:Handler ...

  8. new Handler()和new Handler(Looper.getMainLooper())的区别

    一个帖子的整理: Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别如果你不带参数的实例化:Handler ...

  9. Handler,Looper,MessageQueue流程梳理

    目的:handle的出现主要是为了解决线程间通讯. 举个例子,android是不允许在主线程中访问网络,因为这样会阻塞主线程,影响性能,所以访问网络都是放在子线程中执行,对于网络返回的结果则需要显示在 ...

随机推荐

  1. 深入剖析Kubernetes学习笔记:开篇词(00)

    一.关于Kubernetes初学的疑惑 就在这场因"容器"而起的技术变革中,kubernetes项目已经成为容器技术的事实标准,重新定义了基础设置领域对应用编排与管理的种种可能 1 ...

  2. 第八节: Quartz.Net五大构件之SimpleThreadPool及其四种配置方案

    一. 简介 揭秘: SimpleThreadPool是Quartz.Net中自带的线程池,默认个数为10个,代表一个Scheduler同一时刻并发的最多只能执行10个job,超过10个的job需要排队 ...

  3. [物理学与PDEs]第5章第4节 本构方程 - 应力与变形之间的关系

    5. 4 本构方程 - 应力与变形之间的关系 5.4.1. 本构关系的一般形式 1. 若 Cauchy 应力张量 ${\bf T}$ 满足 $$\bex {\bf T}({\bf y})=\hat{\ ...

  4. 在Unity3D里使用WinForm

    之前给一个游戏写过MOD,功能大概是在游戏里可以打开一个编辑器,然后可以直接在编辑器里修改到游戏数据. 编辑器UI的实现部分,一开始用的是原生GUI,即OnGUI部分,这种方式虽然最简洁,也不用引用任 ...

  5. “Django用户认证系统”学习资料收集

    首推追梦人物——Django用户认证系统 待续……

  6. 新加坡100M带宽,国内延迟70ms,仅800元

    ▇ 新加坡100M带宽,延迟80msE3_8G_1TB_100M_5IP_800元促:E3_32G_1TB SSD_1200元 ▇ 马来西亚,独享带宽,延迟70msL5630_16G_1TB_15M_ ...

  7. svn 支持中文显示

    https://blog.csdn.net/chentengkui/article/details/77543498 https://blog.csdn.net/bugall/article/deta ...

  8. django drf 基础学习5

    一 简介: 用户登录的验证 二 验证机制:    1 session session需要在服务端存储能够通过session_id而获取的信息,每次请求到达服务端时,需要根据session_id这个ke ...

  9. mysql 分库分表 ~ ShardingSphere生态圈

    一  简介   Apache ShardingSphere是一款开源的分布式数据库中间件组成的生态圈二 成员包含   Sharding-JDBC是一款轻量级的Java框架,在JDBC层提供上述核心功能 ...

  10. [Kubernetes]如何让集群为我们工作?

    前一段时间倒腾k8s的时候,写了一系列的博客,有很多人不理解那样做的意义是什么,为什么要那样做,这篇文章就尝试解释一下,在实际环境中,是如何让集群为我们工作的. 因为只研究了一个月左右的时间,认识难免 ...