上次讲了关于Android多线程中通信中Thread、Handler、Looper等的基础概念和基本用法,用现实世界两个人写信交流的过程来理解是再好不过了。但是不得不说这一套完整的细节的确很繁琐,好在Android中为我们提供了另一个简化的API——HandlerThread,通过使用HandlerThread,我们可以以一种简单的方式开启线程、进行线程通信。Let's do it!

三、HandlerThread

  1)参考文档:http://developer.android.com/reference/android/os/HandlerThread.html

  前面的连篇文章中我都贴出来相应内容的官方文档地址,也斗胆说了一下读文档的重要性。这次我们换一种方式——读源代码,好的代码本身就是一份文档,除了会写还得能读!如何找到Android的源码?不管你用的是不再更新的ADT+Eclipse还是AS(Android studio),你的电脑里一定得下载sdk,在sdk目录下有个叫sources的文件夹,里面放的就是Android的系统源码。(开源大法好!)如果你没有,那就“翻墙”下一份,如何快速更新sdk我会在下一篇博客里写......

  2)HandlerThread源码:

  我在这把源码贴出来方便查看(我电脑上的源码是Android-22的)

package android.os;

/**
* Handy class for starting a new thread that has a looper. The looper can then be
* used to create handler classes. Note that start() must still be called.
*/
public class HandlerThread extends Thread {
//线程的优先级
int mPriority; //线程id
int mTid = -1; //与线程绑定的Looper对象
Looper mLooper; public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
} /**
* Constructs a HandlerThread.
* @param name
* @param priority The priority to run the thread at. The value supplied must be from
* {@link android.os.Process} and not from java.lang.Thread.
*/
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
} /**
* Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
* 这里是你需要实现的部分,你的在这里实现对Handler的准备工作,定义你的Hadnler并实现
*handlerMessage(Message msg)方法。
*/
protected void onLooperPrepared() {
} @Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
} /**
* This method returns the Looper associated with this thread. If this thread not been started
* or for any reason is isAlive() returns false, this method will return null. If this thread
* has been started, this method will block until the looper has been initialized.
* @return The looper.
*/
public Looper getLooper() {
if (!isAlive()) {
return null;
} // If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
} /**
* Quits the handler thread's looper.
* <p>
* Causes the handler thread's looper 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>
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*
* @see #quitSafely
*/
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
} /**
* Quits the handler thread's looper safely.
* <p>
* Causes the handler thread's looper to terminate as soon as all remaining messages
* in the message queue that are already due to be delivered have been handled.
* Pending delayed messages with due times in the future will not be delivered.
* </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>
* If the thread has not been started or has finished (that is if
* {@link #getLooper} returns null), then false is returned.
* Otherwise the looper is asked to quit and true is returned.
* </p>
*
* @return True if the looper looper has been asked to quit or false if the
* thread had not yet started running.
*/
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
} /**
* Returns the identifier of this thread. See Process.myTid().
*/
public int getThreadId() {
return mTid;
}
}

  这里我们重点看两个方法:

   protected void onLooperPrepared() 这是一个在拓展类中需要重写的方法,它完成准备工作,一般是对Handelr进行定义。比如接受到主线程发来的消息时如何做出应对。在后面的示例中我就会对Handler进行定义,在handleMessage(Message msg)中定义行为。

  public void run() 再看这个方法里的内容是不是感到很熟悉,理解了Thread、Handler、Looper等概念后,是不是很容易就读懂了它的意思。对了,拓展HandlerThread时,如果要override run方法一定要记得调用父类的run() 。

  对于其他的方法,在这里就不赘述了,每个方法的前面的注释就详细说明了它们的作用。

  3)一个简单的示例:

  还是一样的,我用一个示例来说明HandlerThread的用法。还是一样的开启线程,等到接收到主线程发来的消息,然后打印打印日志。

布局:

  <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="HandlerThread"/> <Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="send message"/>

拓展的HandlerThread类:

 public class MyThread extends HandlerThread {

     private static final String TAG = "MyThread";
private Handler mHandler; public MyThread() {
super(TAG);
} @Override
protected void onLooperPrepared() {
super.onLooperPrepared();
mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == MainActivity.MSG_MAIN){
handlerRequest(msg.obj);
}
}
};
return;
} private void handlerRequest(Object obj){
Log.d(TAG, "handlerRequest:" + obj + ",thread:" + Thread.currentThread().getName());
Looper looper = Looper.getMainLooper();
Handler handler = new Handler(looper);
handler.post(new Runnable() {
@Override
public void run() {
Log.d(TAG,"message is handled,thread:"+Thread.currentThread().getName());
return;
}
});
return;
} public Handler getHandler() {
return mHandler;
}
}

这次我使用了post方法很主线程进行通信。

Activity代码:

 public class MainActivity extends AppCompatActivity {

     public static final int MSG_MAIN = 100;

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); final MyThread thread = new MyThread();
thread.start();
thread.getLooper(); final Button sendButton = (Button) findViewById(R.id.button);
sendButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Handler handler = thread.getHandler();
Message msg = handler.obtainMessage();
msg.what = MainActivity.MSG_MAIN;
msg.obj="testing HandlerThread";
handler.sendMessage(msg);
return;
}
});
}
}

  Logcat打印日志:

  10-08 11:45:47.152 13949-14004/comfallblank.github.handlerthread D/MyThread: handlerRequest:testing HandlerThread,thread:MyThread
  10-08 11:45:47.162 13949-13949/comfallblank.github.handlerthread D/MyThread: message is handled,thread:main

  这次我在日志中加入了线程名称,这样就可以看出任务执行的线程了。

  到这里,关于Android线程的内容算写完了,本来打算在国庆期间写完了,最后拖拖拉拉延迟了一天。还有国庆长假后第一天上课好累啊!就这样吧!下一篇关于如何快速更新sdk努力在这周写出来。

最后,欢迎大家交流,指正我不正确的地方。

邮箱:fallblank525@gmail.com  QQ:1054746297

Android多线程(三)的更多相关文章

  1. android 多线程

    本章讲述在android开发中,多线程的应用.多线程能够处理耗时的操作并优化程序的性能.本章主要介绍知识点,AsyncTask,Java线程池,ThreadPoolExecutor线程池类.本章案例只 ...

  2. Android多线程分析之五:使用AsyncTask异步下载图像

    Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...

  3. android程序---->android多线程下载(一)

    多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...

  4. Android多线程----异步消息处理机制之Handler详解

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  5. android 多线程断点续传下载

    今天跟大家一起分享下Android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基 ...

  6. android程序---->android多线程下载(二)

    上篇我们讲到了android中下载的断点续传问题,今天我们开始学习下载的多线程问题.本次的多线程源码下载:androdi中多线程下载的实现代码.有关断点续传的问题,请参见博客:android程序--- ...

  7. java多线程以及Android多线程

    Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使得宏观上具有多个线程或者进程同时执行的效果. 进程:在操作系统来说,一个运行的程序或者 ...

  8. android多线程-AsyncTask之工作原理深入解析(上)

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  9. Andoid 更好的Android多线程下载框架

    概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...

随机推荐

  1. Silverlight三维透视+倒影效果

    原文:Silverlight三维透视+倒影效果 知识概要: 1.使用2D内容创建3D体验,了解图像的PlaneProjection属性,具体内容读者自己查看文档. 2.Silverlight图形图形的 ...

  2. easyexcel 读写测试

    <dependencies> <dependency> <groupId>com.alibaba</groupId> <artifactId> ...

  3. XMPP之ios即时通讯客户端开发-配置XMPP基本信息(四)

    前文已经有配置open fire,接下来要通过XMPP框架链接到open fire的服务器: 1.首先要在系统偏好设置里面打开open fire的服务器 2.代码中设置xmpp的myJID 有几个名词 ...

  4. MySQL主从复制架构使用方法

    原文:MySQL主从复制架构使用方法 一. 单个数据库服务器的缺点 数据库服务器存在单点问题 数据库服务器资源无法满足增长的读写请求 高峰时数据库连接数经常超过上限 二. 如何解决单点问题 增加额外的 ...

  5. Java堆/栈/常量池以及String的详细详解(转)------经典易懂系统

    一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...

  6. MSYS是一个小型的GNU环境,包括基本的bash,make等等,与Cygwin大致相当(双击“D:\MinGW\msys\1.0\msys.bat”,启动MinGW终端)

    1 简介   MinGW,是Minimalist GNUfor Windows的缩写.它是一个可自由使用和自由发布的Windows特定头文件和使用GNU工具集导入库的集合,允许你在GNU/Linux和 ...

  7. MATLAB Toolbox Path Cache is out of date and is not being used的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 使用mcc编译MATLAB\R2009a\extern\examples\compiler目录下的hello.m,编译 ...

  8. React中的state与props的再理解

    props可以看做是 property 的缩写的复数,可以翻译为属性,类似于HTML 标签的自定义属性.在大多数React教程里讲 state 和 props 主要的区别在于 props 是不可变的, ...

  9. Cross-Domain Security For Data Vault

    Cross-domain security for data vault is described. At least one database is accessible from a plural ...

  10. 音频、视频等文件格式(.ts、.meta)及其认识

    MPEG:Moving Picture Experts Group,动态图像专家组, JPEG:Joint Photographic Experts Group,联合图像专家组 1. .ts .ts ...