Android多线程(三)
上次讲了关于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多线程(三)的更多相关文章
- android 多线程
本章讲述在android开发中,多线程的应用.多线程能够处理耗时的操作并优化程序的性能.本章主要介绍知识点,AsyncTask,Java线程池,ThreadPoolExecutor线程池类.本章案例只 ...
- Android多线程分析之五:使用AsyncTask异步下载图像
Android多线程分析之五:使用AsyncTask异步下载图像 罗朝辉 (http://www.cnblogs.com/kesalin) CC 许可,转载请注明出处 在本系列文章的第一篇<An ...
- android程序---->android多线程下载(一)
多线程下载是加快下载速度的一种方式,通过开启多个线程去执行一个任务,可以使任务的执行速度变快.多线程的任务下载时常都会使用得到断点续传下载,就是我们在一次下载未结束时退出下载,第二次下载时会接着第一次 ...
- Android多线程----异步消息处理机制之Handler详解
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- android 多线程断点续传下载
今天跟大家一起分享下Android开发中比较难的一个环节,可能很多人看到这个标题就会感觉头很大,的确如果没有良好的编码能力和逻辑思维,这块是很难搞明白的,前面2次总结中已经为大家分享过有关技术的一些基 ...
- android程序---->android多线程下载(二)
上篇我们讲到了android中下载的断点续传问题,今天我们开始学习下载的多线程问题.本次的多线程源码下载:androdi中多线程下载的实现代码.有关断点续传的问题,请参见博客:android程序--- ...
- java多线程以及Android多线程
Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使得宏观上具有多个线程或者进程同时执行的效果. 进程:在操作系统来说,一个运行的程序或者 ...
- android多线程-AsyncTask之工作原理深入解析(上)
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- Andoid 更好的Android多线程下载框架
概述 为什么是更好的Android多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...
随机推荐
- [Django] Get started with Django -- Install python and virtualenv
Install python3 on MacOS: brew install python3 Come alone with python3, there are also some other to ...
- BZOJ 3524 - 主席树
传送门 题目分析 标准主席树,按照位置插入每个数,对于询问l, r, 在l-1,r两树上按照线段树搜索次数大于(r - l + 1) / 2的数. code #include<bits/stdc ...
- cxf整合spring发布rest服务 httpclient访问服务
1.创建maven web项目并添加依赖 pom.xml <properties> <webVersion>3.0</webVersion> <cxf.ver ...
- Mina、Netty、Twisted一起学习(三):TCP前缀固定大小的消息(Header)
于以前的博文于,有介绍切割消息换行的方法. 但是有一个小问题,这样的方法,设消息中本身就包括换行符,那将会将这条消息切割成两条.结果就不正确了. 本文介绍第二种消息切割方式,即上一篇博文中讲的第2条: ...
- 世界卫生组织(WHO)发出最新警告:埃博拉疫情应急响应
10月14r日.世界卫生组织(WHO)发出警告:在未来两个月内,西非国家将面对"could face up to 10 thousand new Ebola cases a week wit ...
- 《用户体验要素》澄清了 UI 原型设计中看不见确感受得到的那一层
<用户体验要素>澄清了看不见确感受得到的那一层 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&quo ...
- Android 项目框架功能整理记录
用来记录自己在项目用到的框架工具等,新人新记录,希望能对你搭建项目有所帮助 常用框架整理 视图绑定注解框架: butterKnife 网络请求框架: OKHttp 图片加载缓存:Gilde 数据格式解 ...
- Editplus配置Python的开发环境
Python 有很多集成开发工具,商业的有komodo,Wingide,Boa 等,还有Python 自带的集成环境IDLE,Windows 下还有PythonWin 等.但是,这些工具有的是过于复杂 ...
- 嵌入式OS入门注意事项-同RTX案件:九.关于优先-翻转,继承和天花板
嵌入式OS入门注意事项-同RTX案件:九.关于优先-翻转,继承和天花板 涉及当调度优先级,会有很多问题,本文中,优先调度和一些战略的主要问题,以应付. 有几个概念如下:(priority invers ...
- c#如何获得ModelVisual3D中MeshGeometry3D对象
原文:c#如何获得ModelVisual3D中MeshGeometry3D对象 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671 ...