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多线程下载框架呢,原因你懂的,广告法嘛! 本篇我们我们就来聊聊多线程下载框架,先聊聊我们框架的特点: 多线程 多任务 断点续传 支持大文件 可以自定义下载数据库 高度 ...
随机推荐
- [HTML5] Using the tabindex attribute for keyboard accessibility
You can make any element keyboard interactive with the HTML tabindex attribute. But you might need a ...
- WPF实现射线效果动画
原文:WPF实现射线效果动画 最近的一个项目中有个需求是:从一个点向其它多个点发出射线,要求这些射线同时发出,同时到达. 我就想到了用WPF的动画来实现.WPF中有Line类用于绘制直线,但这个类中好 ...
- POJ 2104 - 主席树 / 询问莫队+权值分块
传送门 题目大意应该都清楚. 今天看到一篇博客用分块+莫对做了这道题,直接惊呆了. 首先常规地离散化后将询问分块,对于某一询问,将莫队指针移动到指定区间,移动的同时处理权值分块的数字出现次数(单独.整 ...
- 【9302】&&【a301】兔子繁殖
Time Limit: 10 second Memory Limit: 2 MB 问题描述 有一种兔子,出生后一个月就可以长大,然后再过一个月一对长大的兔子就可以生育一对小兔子且以后每个月都能生育一对 ...
- 开源项目学习之------AG-Admin环境搭建
原文地址: https://blog.csdn.net/u011781521/article/details/79056974 一.框架简介 AG-Admin是基于Spring Cloud微服务化开发 ...
- Spring+SpringMVC+MyBatis+easyUI
Spring+SpringMVC+MyBatis+easyUI 日常啰嗦 还好在第一篇文章里就列好了接下来的主线及要写的知识点,不然都不知道要写什么东西了,开篇里已经列了基础篇要讲svn和git的知识 ...
- wxWidgets编译和在VC 6.0中的配置
1. 安装 运行wxMSW-2.8.3-Setup1.exe,将之安装到不带空格符号的目录中,本例为C:/wxWidgets-2.8.3: 2. 编译和配置 (1) 用VC6.0编译 进入C: ...
- WPF中使用Hashtable剔除重复字符串(比如电话号码)
原文:WPF中使用Hashtable剔除重复字符串(比如电话号码) 本文中的输入框中的字符串是逗号隔开的,你可以换成其他特别的字符串.本篇中的亮点:1. 里面有一个玻璃样式按钮,用XAML制作2. W ...
- Python抓取小说
Python抓取小说 前言 这个脚本命令MAC在抓取小说写,使用Python它有几个码. 代码 # coding=utf-8 import re import urllib2 import chard ...
- MySQL更改表的存储引擎
MySQL它提供了多种数据库存储引擎,存储引擎负责MySQL存储和检索数据的数据库.不同的存储引擎具有不同的特性,能须要将一个已经存在的表的存储引擎转换成另外的一个存储引擎.有非常多方法能够完毕这样的 ...