Android HandlerThread 总结使用

Android HandlerThread 总结使用

转载请标明出处:http://www.cnblogs.com/zhaoyanjun/p/6062880.html
本文出自【赵彦军的博客】

前言

以前我在 【Android Handler、Loop 的简单使用】 介绍了子线程和子线程之间的通信。
这里写图片描述

很明显的一点就是,我们要在子线程中调用Looper.prepare() 为一个线程开启一个消息循环,默认情况下Android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环。) Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。 然后通过Looper.loop() 让Looper开始工作,从消息队列里取消息,处理消息。

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

然而这一切都可以用HandlerThread类来帮我们做这些逻辑操作。

HandlerThread

HandlerThread本质上就是一个普通Thread,只不过内部建立了Looper.

HandlerThread的常规用法

  • 创建一个HandlerThread

mThread = new HandlerThread("handler_thread");

  • 启动一个HandlerThread

    mThread.start();

  • 退出循环
    Looper是通过调用loop方法驱动着消息循环的进行: 从MessageQueue中阻塞式地取出一个消息,然后让Handler处理该消息,周而复始,loop方法是个死循环方法。

那如何终止消息循环呢?我们可以调用Looper的quit方法或quitSafely方法,二者稍有不同。

 /*** Quits the looper.* <p>* Causes the {@link #loop} method to terminate without processing any* more messages in the message queue.* </p><p>* Any attempt to post messages to the queue after the looper is asked to quit will fail.* For example, the {@link Handler#sendMessage(Message)} method will return false.* </p><p class="note">* Using this method may be unsafe because some messages may not be delivered* before the looper terminates.  Consider using {@link #quitSafely} instead to ensure* that all pending work is completed in an orderly manner.* </p>** @see #quitSafely*/public void quit() {mQueue.quit(false);}/*** Quits the looper safely.* <p>* Causes the {@link #loop} method to terminate as soon as all remaining messages* in the message queue that are already due to be delivered have been handled.* However pending delayed messages with due times in the future will not be* delivered before the loop terminates.* </p><p>* Any attempt to post messages to the queue after the looper is asked to quit will fail.* For example, the {@link Handler#sendMessage(Message)} method will return false.* </p>*/public void quitSafely() {mQueue.quit(true);}

相同点:
将不在接受新的事件加入消息队列。

不同点
当我们调用Looper的quit方法时,实际上执行了MessageQueue中的removeAllMessagesLocked方法,该方法的作用是把MessageQueue消息池中所有的消息全部清空,无论是延迟消息(延迟消息是指通过sendMessageDelayed或通过postDelayed等方法发送的需要延迟执行的消息)还是非延迟消息。

当我们调用Looper的quitSafely方法时,实际上执行了MessageQueue中的removeAllFutureMessagesLocked方法,通过名字就可以看出,该方法只会清空MessageQueue消息池中所有的延迟消息,并将消息池中所有的非延迟消息派发出去让Handler去处理,quitSafely相比于quit方法安全之处在于清空消息之前会派发所有的非延迟消息。

无论是调用了quit方法还是quitSafely方法只会,Looper就不再接收新的消息。即在调用了Looper的quit或quitSafely方法之后,消息循环就终结了,这时候再通过Handler调用sendMessage或post等方法发送消息时均返回false,表示消息没有成功放入消息队列MessageQueue中,因为消息队列已经退出了。

需要注意的是Looper的quit方法从API Level 1就存在了,但是Looper的quitSafely方法从API Level 18才添加进来。

小例子:

package com.app;import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;public class MainActivity extends AppCompatActivity {private HandlerThread myHandlerThread ;private Handler handler ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//创建一个线程,线程名字:handler-threadmyHandlerThread = new HandlerThread( "handler-thread") ;//开启一个线程myHandlerThread.start();//在这个线程中创建一个handler对象handler = new Handler( myHandlerThread.getLooper() ){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作Log.d( "handler " , "消息: " + msg.what + "  线程: " + Thread.currentThread().getName()  ) ;}};//在主线程给handler发送消息handler.sendEmptyMessage( 1 ) ;new Thread(new Runnable() {@Overridepublic void run() {//在子线程给handler发送数据handler.sendEmptyMessage( 2 ) ;}}).start() ;}@Overrideprotected void onDestroy() {super.onDestroy();//释放资源myHandlerThread.quit() ;}
}

运行效果:

/com.app D/handler: 消息: 1  线程: handler-thread
/com.app D/handler: 消息: 2  线程: handler-thread

HandlerThread的特点

  • HandlerThread将loop转到子线程中处理,说白了就是将分担MainLooper的工作量,降低了主线程的压力,使主界面更流畅。

  • 开启一个线程起到多个线程的作用。处理任务是串行执行,按消息发送顺序进行处理。HandlerThread本质是一个线程,在线程内部,代码是串行处理的。

  • 但是由于每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。

  • HandlerThread拥有自己的消息队列,它不会干扰或阻塞UI线程。

  • 对于网络IO操作,HandlerThread并不适合,因为它只有一个线程,还得排队一个一个等着。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/463716.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[MathType需要安装新版的MT EXtra字体]解决方法

MathType是一款强大的数学公式编辑器&#xff0c;当安装完成&#xff08;或者使用绿色版&#xff09;打开程序时&#xff0c;常常弹出缺少字体的对话框&#xff0c;如下&#xff1a; MathType需要一个新版的MT Extra&#xff08;TrueType&#xff09;字体。请重新安装MathType&…

Microsoft Lync

转载于:https://blog.51cto.com/dynamicit/874659

python 文件操作练习

1. 文件a.txt内容&#xff1a;每一行内容分别为商品名字&#xff0c;价钱&#xff0c;个数。 apple 10 3 tesla 100000 1 mac 3000 2 lenovo 30000 3 chicken 10 3 通过代码&#xff0c;将其构建成这种数据类型&#xff1a;[{name:apple,price:10,amount:3},{name:tesla,price:…

超级简单的数学题

超级简单的数学题有5人坐在一起&#xff0c;当问第5个人多少岁,他说比第4个人大2岁&#xff0c;问第4个人多少岁,他说比第3个人大2岁&#xff0c;依此下去&#xff0c;问第一个人多少岁&#xff0c;他说他10岁&#xff0c;最后求第5个人多少岁如果所坐的不是5人而是n人&#xf…

Linux下共享内存的查看和释放

说明&#xff1a;1、查看共享内存&#xff0c;使用命令&#xff1a;ipcs -m2、删除共享内存&#xff0c;使用命令&#xff1a;ipcrm -m [shmid]使用如下&#xff1a;[plain] view plaincopy[negivupnegivup mycode]$ ipcs -m 查看共享内存区 ------…

微软发布Enterprise Library 4.1和Unity 1.2

说明 微软模式与实践团队今天发布了Enterprise Library 4.1和Unity 1.2版本&#xff0c;这次发布的主要新特性如下&#xff1a; 1. 支持Visual Studio 2008 SP1 2. Unity应用程序块中加入了拦截机制 3. 性能提升 4. 配置工具的可用性提升 5. Bugs修复。 在Unity 1.2中有如下几点…

简易的波形折叠电路

01 波形折叠一、背景介绍今天在 Youtube 上看到 UP 主 Neukolln 展示了一款非常简单波形折叠电路。那么什么是波形折叠电路&#xff1f;它有什么用处&#xff1f;1、什么是波形折叠&#xff1f;通常情况下&#xff0c;信号在放大中会产生“饱和失真”&#xff0c;这是由于放大器…

STL 容器和迭代器连载6_顺序容器的操作3

2019独角兽企业重金招聘Python工程师标准>>> /*- * 文件名 &#xff1a;STL_con_ite_6.cpp * 开发人员&#xff1a;袁培荣 * 当前版本&#xff1a;1.0.0.2595 * 创建时间&#xff1a;2012-05-24 * 修改时间&#xff1a;2012-05-24 * 功能…

hive三种调用方式

一、hive -e ‘sql语句’ &#xff08;shell命令&#xff09; 适合比较短的sql语句调用&#xff0c;优点是可以直接在shell中调用静音模式 -S 在执行HiveQL过程中&#xff0c;不在显示器输出MR的执行过程hive -S -e ‘sql语句’ > test.txt 将执行结果直接输入到本地文件 二…

vector的内存释放

1. vector容器的内存自增长 与其他容器不同&#xff0c;其内存空间只会增长&#xff0c;不会减小。先来看看"C Primer"中怎么说&#xff1a;为了支持快速的随机访问&#xff0c;vector容器的元素以连续方式存放&#xff0c;每一个元素都紧挨着前一个元素存储。设想一…

从程序语言排行榜来解读IT及Web的发展

预测行业的发展不能是凭空预测&#xff0c;而需要有根据。因为预测本身就是个不太准的事情&#xff0c;再没根据的话&#xff0c;那就更是浮云了。下面&#xff0c;我尝试从程序语言排行榜来解读一下IT的发展方向及Web的未来。《2012年4月份编程语言排行榜》全文见 http://news…

QT - 内存泄漏检测

一、安装vld-2.5.1-setup.exe 下载地址&#xff1a;https://archive.codeplex.com/?pvld 二、pro中添加头文件目录与库目录 INCLUDEPATH "C:\\Program Files (x86)\\Visual Leak Detector\\include"LIBS "C:\\Program Files (x86)\\Visual Leak Detector\\li…

C和C++混合编程(__cplusplus 与 external c 的使用)

第一种理解比如说你用C开发了一个DLL库&#xff0c;为了能够让C语言也能够调用你的DLL输出(Export)的函数&#xff0c;你需要用extern "C"来强制编译器不要修改你的 函数名。 通常&#xff0c;在C语言的头文件中经常可以看到类似下面这种形式的代码&#xff1a; #ifd…

Eclipse开发Android程序如何在手机上运行

http://www.cnblogs.com/plwang1990/archive/2011/07/04/2097757.htm android开发不论是在真机上调试还是最终发布到真机上都非常简单&#xff0c;过程如下&#xff1a; 1、安装usb驱动 手机要能与电脑相连&#xff0c;当然要安驱动了。效果就是你插入手机&#xff0c;电脑显示…

Python 字符串 String 内建函数大全(1)

关于 Python 的字符串处理相关的方法还是非常多的&#xff0c;由于我正在学习 Python&#xff0c;于是就把 Python 中这些混杂的用于 string 的函数总结出来&#xff0c;在自己忘记的时候便于查找&#xff0c;希望对于有类似需求的人有所帮助。 captalize() 函数 功能 将一个字…

表单PostGet两个长度限制问题的分析

一、问题起因在某项目释放后Bug统计的附件《释放后问题》里有&#xff1a; 问题 原因 分析 备注 CSV处理时&#xff0c;如果处理的主题数过多&#xff0c;发生URL参数上限的错误&#xff1b; 可变长度的参数通过URL方式传递&#xff0c;会造成这种潜在的错误发生。 1、属于2次…

poj 2096 , zoj 3329 , hdu 4035 —— 期望DP

题目&#xff1a;http://poj.org/problem?id2096 题目好长...意思就是每次出现 x 和 y&#xff0c;问期望几次 x 集齐 n 种&#xff0c;y 集齐 s 种&#xff1b; 所以设 f[i][j] 表示已经有几种&#xff0c;转移一下即可。 代码如下&#xff1a; #include<cstdio> #incl…

vector占用内存的释放

vector<int> v1; v1.push_back(9); {Vector<int>tmp v1;V1.swap(tmp); } 使用{ }的目的是让tmp退出{ }时自动析构。 标准解决办法&#xff1a; template < class T > void ClearVector( vector< T >&vt ) {vector< T > vtTemp; veTemp.swa…

[C++]MySQL数据库操作实例

由于课程大实验需要使用c操作MySQL数据库&#xff0c;经过一番研究终于成功实现VS2008中与MySQL的连接。环境设置&#xff1a;安装完MySQL之后&#xff0c;将安装目录中的include目录下的libmysql.lib文件拷到VS2008安装目录中的VC\lib\下&#xff0c;然后在项目-选项-c/c-常规…

JS面向对象编程实现

Function 在 中是一个很特殊的对象&#xff0c;其特殊性体现在它的多重身份。 Function 可以声明普通的函数&#xff0c;这一点和其他语言中的函数概念是相同的。除此以外&#xff0c;Function还可以用作类型的声明和实现、对象的构造函数&#xff0c;以及类引用。 Apply和Call…