首先,我们需要创建一个名为DownloadThread 的类,该类继承自 HandlerThread。这个类的主要目的是用于下载功能。

```java

public class DownloadThread extends HandlerThread {

private static final String TAG = "DownloadThread";

public static final int TYPE_START = 2; // 通知主线程任务开始

public static final int TYPE_FINISHED = 3; // 通知主线程任务结束

private Handler mUIHandler; // 主线程的Handler

public DownloadThread(String name) {

super(name);

}

@Override

protected void onLooperPrepared() {

Log.e(TAG, "onLooperPrepared: 1.Download线程开始准备");

super.onLooperPrepared();

}

//注入主线程Handler

public void setUIHandler(Handler UIhandler) {

mUIHandler = UIhandler;

Log.e(TAG, "setUIHandler: 2.主线程的handler传入到Download线程");

}

//Download线程开始下载

public void startDownload() {

Log.e(TAG, "startDownload: 3.通知主线程,此时Download线程开始下载");

mUIHandler.sendEmptyMessage(TYPE_START);

//模拟下载

Log.e(TAG, "startDownload: 5.Download线程下载中...");

SystemClock.sleep(2000);

Log.e(TAG, "startDownload: 6.通知主线程,此时Download线程下载完成");

mUIHandler.sendEmptyMessage(TYPE_FINISHED);

}

}

```

```

public class MainActivity extends AppCompatActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

}

```

```java

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

private DownloadThread mHandlerThread; //子线程

private Handler mUIhandler; //主线程的Handler

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//初始化,参数为线程的名字

mHandlerThread = new DownloadThread("mHandlerThread");

//调用start方法启动线程

mHandlerThread.start();

//初始化Handler,传递 mHandlerThread 内部的一个 looper

mUIhandler = new Handler(mHandlerThread.getLooper()) {

@Override

public void handleMessage(Message msg) {

//判断mHandlerThread里传来的msg,根据msg进行主页面的UI更改

switch (msg.what) {

case DownloadThread.TYPE_START:

//不是在这里更改UI哦,只是说在这个时间,你可以去做更改UI这件事情,改UI还是得在主线程。

Log.e(TAG, "4.主线程知道Download线程开始下载了...这时候可以更改主界面UI");

break;

case DownloadThread.TYPE_FINISHED:

Log.e(TAG, "7.主线程知道Download线程下载完成了...这时候可以更改主界面UI,收工");

break;

default:

break;

}

super.handleMessage(msg);

}

};

//子线程注入主线程的mUIhandler,可以在子线程执行任务的时候,随时发送消息回来主线程

mHandlerThread.setUIHandler(mUIhandler);

//子线程开始下载

mHandlerThread.startDownload();

}

@Override

protected void onDestroy() {

//有2种退出方式

//mHandlerThread.quit();

//mHandlerThread.quitSafely(); 需要API >=18

super.onDestroy();

}

}

```

以下是重构后的代码,并保持了原有的段落结构:

```java

public class HandlerThread extends Thread {

int mPriority; // 优先级

int mTid = -1; // 线程ID

Looper mLooper; // 自带的Looper

private @Nullable Handler mHandler; // Handler对象,可以为null

public HandlerThread(String name) {

super(name);

mPriority = Process.THREAD_PRIORITY_DEFAULT;

}

/**

* 构造一个HandlerThread。

* @param name 线程名

* @param priority 要运行线程的优先级。提供的值必须来自{@link android.os.Process},而不是来自java.lang.Thread。

*/

public HandlerThread(String name, int priority) {

super(name);

mPriority = priority;

}

}

```

源码解析:

- `HandlerThread`类继承自`Thread`类,表示一个自定义的线程类。

- `mPriority`成员变量用于存储线程的优先级,取值范围从`android.os.Process.THREAD_PRIORITY_DEFAULT`到`android.os.Process.THREAD_PRIORITY_BACKGROUND`,默认为`THREAD_PRIORITY_DEFAULT`。

- `mTid`成员变量用于存储线程的ID,初始化为-1。

- `mLooper`成员变量用于存储线程的Looper对象,它是Android系统中的一个基本组件,用于处理消息队列。

- `mHandler`成员变量用于存储Handler对象,它负责在线程中处理消息和执行任务。这个成员变量可以为null。

构造函数方面,有两个重载版本:

- 一个不带参数的构造方法,接受一个字符串作为线程名字,并将线程的优先级设置为`THREAD_PRIORITY_DEFAULT`。

- 一个带有两个参数的构造方法,分别接受一个字符串和一个整数作为线程名字和优先级。这个构造方法将线程的优先级设置为传入的整数值。

```

/**

* Call back method that can be explicitly overridden if needed to execute some

* setup before Looper loops.

*/

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;

}

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;

}

```

public Handler getThreadHandler() {

if (mHandler == null) {

mHandler = new Handler(getLooper());

}

return mHandler;

}

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;

}

这两个方法的区别在于,`quit()` 方法会立即停止消息循环,而 `quitSafely()` 方法则会在停止消息循环后等待一段时间,以确保所有正在处理的消息都已经被处理完毕。这意味着在调用 `quitSafely()` 方法时,可能会有部分消息未能被处理。如果不关心这些未处理的消息,可以选择使用 `quit()` 方法。

这段代码是一个名为`quit`的方法,它接受一个布尔类型参数`safe`。该方法的作用是退出应用程序或者停止某个操作。如果`safe`为`true`,则在清空消息之前会派发所有的非延迟消息;如果`safe`为`false`,则直接清空所有的消息,包括延迟消息和非延迟消息。

具体实现过程如下:

1. 首先检查是否允许退出,如果不允许,则抛出异常。

2. 使用`synchronized`关键字对当前对象进行同步,确保在同一时刻只有一个线程可以执行该方法。

3. 判断是否正在退出,如果是,则直接返回。

4. 将`mQuitting`设置为`true`,表示正在退出。

5. 根据`safe`参数的值,调用不同的方法来清空消息池中的不同类型的消息。

6. 调用`nativeWake(mPtr)`方法唤醒主线程。

HandlerThread 和 Looper 是 Android 开发中用于实现消息循环的两个重要组件。它们之间的主要区别在于如何终止消息循环以及处理退出时的情况。

## quit 方法

`quit()` 方法是 HandlerThread 类的一个成员方法,用于安全地终止消息循环。这个方法从 API 1 就开始存在了,比较早。当调用 `quit()` 方法后,Looper 将立即停止接收新的消息,并且不再将消息放入消息队列中。这意味着在调用 `quit()` 方法之后,通过 Handler 发送的消息不会被处理。以下是一个简单的示例:

```java

public class MyHandlerThread extends HandlerThread {

public MyHandlerThread(String name) {

super(name);

}

@Override

public void run() {

Looper.prepare();

Handler handler = new MyHandler();

handler.sendEmptyMessage(0);

Looper.loop();

}

}

```

```java

public class MyActivity extends AppCompatActivity {

private MyHandlerThread mHandlerThread;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

mHandlerThread = new MyHandlerThread("MyHandlerThread");

mHandlerThread.start();

}

@Override

protected void onDestroy() {

super.onDestroy();

mHandlerThread.quitSafely(); // 注意这里使用了 quitSafely 而不是 quit

}

}

```

在上面的代码中,我们在 `MyActivity` 的 `onDestroy()` 方法中调用了 `mHandlerThread.quitSafely()`,以确保在活动销毁时能够安全地结束消息循环。如果不使用 `quitSafely`,则可能会导致内存泄漏或者应用程序异常退出。

## quitSafely 方法(API 18+)

从 Android API 18(Android 6.0 Marshmallow)开始,`HandlerThread` 还提供了一个名为 `quitSafely()` 的方法。这个方法与 `quit()` 在功能上相似,但它可以更优雅地处理退出时的场景。当调用 `quitSafely()` 或者 `quit()` 时,Looper 将尝试优雅地停止接收新的消息,并通知所有已注册的处理器进行清理工作。在处理完所有消息后,Looper 将关闭自身。以下是一个简单的示例:

```java

public class MyHandlerThread extends HandlerThread {

public MyHandlerThread(String name) {

super(name);

}

@Override

public void run() {

Looper.prepare();

Handler handler = new MyHandler();

handler.sendEmptyMessage(0);

Looper.loop();

}

}

```

```java

public class MyActivity extends AppCompatActivity {

private MyHandlerThread mHandlerThread;

{

mHandlerThread = new MyHandlerThread("MyHandlerThread");

mHandlerThread.start();

}

}

```