HandlerThread是Android API提供的一个方便、便捷的类,使用它我们可以快速的创建一个带有Looper的线程。Looper可以用来创建Handler实例。注意:start()仍然必须被调用。
以下是HandlerThread使用的示例代码:
```java
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
public class HandlerDemo {
private static final String TAG = "HandlerDemo";
public static void main(String[] args) {
// 创建HandlerThread
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
// 获取Looper
Looper looper = handlerThread.getLooper();
// 在Looper中创建Handler并处理消息
Handler handler = new Handler(looper) {
@Override
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
Log.d(TAG, "收到消息:" + msg.what);
}
};
// 发送消息到HandlerThread中的Handler进行处理
Message message = handlerThread.obtainMessage();
message.what = 1;
message.obj = "Hello, Handler!";
handler.sendMessage(message);
}
}
```
在上述代码中,首先创建了一个名为"MyHandlerThread"的HandlerThread对象,并通过start()方法启动线程。然后通过getLooper()方法获取到该线程的Looper对象。接下来,在Looper中创建了一个自定义的Handler对象,并重写了handleMessage()方法来处理接收到的消息。最后,通过handlerThread.obtainMessage()方法获取一个消息对象,并设置了消息的类型和内容,然后通过handler.sendMessage()方法将消息发送给HandlerThread中的Handler进行处理。
以下是重构后的代码:
```java
package com.zpengyong.hand;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private final static String TAG = "MainActivity";
private Button mGet;
private TextView mResult;
protected final int MSG_GET = 1;
protected final int MSG_RESULT = 2;
private HandlerThread mHandlerThread;
//子线程中的Handler实例。
private Handler mSubThreadHandler;
//与Ui线程绑定的Handler实例。
private Handler mUiHandler = new Handler() {
public void handleMessage(Message msg) {
Log.i(TAG, "mUiHandler handleMessage thread:" + Thread.currentThread());
switch (msg.what) {
case MSG_RESULT:
mResult.setText((String) msg.obj);
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate thread:" + Thread.currentThread());
mGet = (Button) findViewById(R.id.get);
mGet.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mSubThreadHandler.sendEmptyMessage(MSG_GET);
}
});
mResult = (TextView) findViewById(R.id.result);
initHandlerThraed();
}
private void initHandlerThraed() {
//创建HandlerThread实例
mHandlerThread = new HandlerThread("handler_thread");
//开始运行线程
mHandlerThread.start();
//获取HandlerThread线程中的Looper实例
Looper loop = mHandlerThread.getLooper();
//创建Handler与该线程绑定。
mSubThreadHandler = new Handler(loop) {
public void handleMessage(Message msg) {
Log.i(TAG, "mSubThreadHandler handleMessage thread:" + Thread.currentThread());
switch (msg.what) {
case MSG_GET:
try { //模拟延时处理
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
double number = Math.random();
String result = "number:" + number; //向ui线程发送消息,更新ui。
Message message = new Message();
message.what = MSG_RESULT;
message.obj = result;
mUiHandler.sendMessage(message);
break;
default:
break;
}
}
};
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy"); //退出HandlerThread的Looper循环。mHandlerThread.quit();
上述代码相对简单,功能也较为基础。在此基础上,我们可以进行一些扩展和优化。
首先,在Activity创建时调用`initHandlerThraed()`函数:
```java
private Handler mSubThreadHandler;
private Handler mUiHandler;
private HandlerThread mHandlerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initHandlerThraed();
}
private void initHandlerThraed() {
mSubThreadHandler = new Handler(new HandlerThread("sub_thread").start());
mUiHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// 在主线程中更新UI界面
switch (msg.what) {
case 1:
// TODO: 根据消息内容更新UI界面
break;
}
}
};
}
```
接下来,多次点击按钮,打印信息如下所示:
```yaml
07-13 05:15:07.662: I/MainActivity(1472): onCreate thread:Thread[main,5,main] 07-13 05:15:45.382: I/MainActivity(1472): mSubThreadHandler handleMessage thread:Thread[handler_thread,5,main] 07-13 05:15:46.402: I/MainActivity(1472): mUiHandler handleMessage thread:Thread[main,5,main] 07-13 05:15:46.412: I/MainActivity(1472): mSubThreadHandler handleMessage thread:Thread[handler_thread,5,main] 07-13 05:15:47.412: I/MainActivity(1472): mUiHandler handleMessage thread:Thread[main,5,main] .....
```
点击按钮,向`mSubThreadHandler`发送消息,`mSubThreadHandler`接收到消息后进行处理。从打印的信息可以看出,`mSubThreadHandler`的`handleMessage`方法运行在子线程中。模拟耗时操作,生成随机数,然后向主线程中的`mUiHandler`发送消息(Message)。`mUiHandler`的`handleMessage`方法运行在主线程,可以用来更新UI界面。当Activity销毁时,调用`mHandlerThread.quit()`退出`HandlerThread`的Looper循环。效果图如下:
```markdown
2. HandlerThread源码分析
HandlerThread是Android系统中的一个类,它继承自Thread类。我们可以通过查看源码来了解HandlerThread的构造方法和run()方法。
首先,我们来看一下HandlerThread的构造方法:
```java
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
// 参数为线程名称
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
// 参数为线程名称和优先级
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
}
```
HandlerThread提供了两个构造方法,分别是:
1. `HandlerThread(String name)`:参数为线程名称,线程优先级默认为`Process.THREAD_PRIORITY_DEFAULT`。
2. `HandlerThread(String name, int priority)`:参数为线程名称和设置的线程优先级。
接下来,我们来看一下线程运行的run()方法:
```java
@Override
public void run() {
mLooper = new Looper();
mTid = getId();
}
```
在run()方法中,首先创建了一个Looper对象,然后获取了当前线程的ID并赋值给mTid。这样,HandlerThread就可以根据mTid来处理消息队列中的任务。
protected void onLooperPrepared() {
}
@Override
public void run() {
//获取进程id
mTid = Process.myTid();
//创建Looper实例
Looper.prepare();
synchronized (this) {
//获取当前线程的Looper实例
mLooper = Looper.myLooper();
notifyAll();
}
//设置线程优先级
Process.setThreadPriority(mPriority);
onLooperPrepared();
//开始循环
Looper.loop();
mTid = -1;
}
此方法返回与此线程关联的Looper。 如果此线程未启动或由于任何原因isAlive()返回false,此方法将返回null。
```java
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// 如果这个线程已经启动,将会被阻塞,直到mLooper被初始化为止。
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
```
在HandlerThread的run()方法中,我们会为该线程创建一个Looper实例并赋值给mLooper变量。getLooper()方法则是在主线程中调用,用于获取与该线程绑定的Looper实例。如果线程未启动或者已经死亡(isAlive()返回false),则该方法会返回null。
接下来,通过该looper实例创建Handler:
```java
// 创建Handler与该线程绑定。 mSubThreadHandler = new Handler(loop)
```
你可能会好奇为什么要这样长久Handler而不是“new Handler()“这样呢?因为我们要创建的Handler要与子线程绑定到一起,要处理子线程中的消息,所以要通过子线程中的looper(有线程对应的消息队列)实例创建Handler。这样通过mSubThreadHandler发送的消息会添加到子线程中的消息队列中,然后Looper实例消息进行分发,交给mSubThreadHandler进行处理。
```java
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
```
HandlerThread是Android中用于处理本地IO读写操作(如数据库、文件)的线程。它适合在单线程+异步队列的形式下运行,因为本地IO操作大多数耗时在毫秒级别,这样的方式不会对后面的请求产生较大阻塞。而网络操作相对耗时,容易阻塞后续请求,因此在HandlerThread中不适合加入网络操作。
quit和quitSafely方法都是用于退出HandlerThread的消息循环。它们都调用Looper的quit或quitSafely方法,但它们的区别在于:
- quit方法会将消息队列中的所有消息移除(包括延迟消息和非延迟消息)。
- quitSafely方法只会将消息队列中的所有延迟消息移除,而非延迟消息则会被派发给Handler去处理。与quit相比,quitSafely在清空消息之前会派发所有的非延迟消息,因此更加安全。