Skip to content

Commit f0472f6

Browse files
authored
Merge pull request LRH1993#28 from Notzuonotdied/master
调整了文章的编辑细节。
2 parents 4e2e2ab + fdd0a51 commit f0472f6

File tree

8 files changed

+597
-588
lines changed

8 files changed

+597
-588
lines changed

android/basis/HandlerThread.md

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
**我们知道在Android系统中,我们执行完耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁。想象一下如果我们在项目中经常要执行耗时操作,如果经常要开启线程,接着又销毁线程,这无疑是很消耗性能的?那有什么解决方法呢?**
1+
**我们知道在Android系统中,我们执行完耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁。想象一下如果我们在项目中经常要执行耗时操作,如果经常要开启线程,接着又销毁线程,这无疑是很消耗性能的那有什么解决方法呢?**
22

33
1. 使用线程池
44
2. 使用HandlerThread
@@ -12,7 +12,7 @@
1212

1313
### 使用场景
1414

15-
HandlerThread是Google帮我们封装好的,可以用来执行多个耗时操作,而不需要多次开启线程,里面是采用handler和Looper实现的
15+
HandlerThread是Google帮我们封装好的,可以用来执行多个耗时操作,而不需要多次开启线程,里面是采用Handler和Looper实现的。
1616

1717
> 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.
1818
@@ -35,7 +35,7 @@ handlerThread.start();
3535
1. 将我们的handlerThread与Handler绑定在一起。
3636
还记得是怎样将Handler与线程对象绑定在一起的吗?其实很简单,就是将线程的looper与Handler绑定在一起,代码如下:
3737

38-
```java
38+
``` java
3939
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
4040
@Override
4141
public void handleMessage(Message msg) {
@@ -51,34 +51,37 @@ mThreadHandler = new Handler(mHandlerThread.getLooper()) {
5151

5252
### 完整测试代码如下
5353

54-
```java
54+
``` java
5555
public class MainActivity extends AppCompatActivity {
56-
private TextView mTv;
56+
private static final int MSG_UPDATE_INFO = 0x100;
5757
Handler mMainHandler = new Handler();
58+
private TextView mTv;
5859
private Handler mThreadHandler;
59-
private static final int MSG_UPDATE_INFO = 0x100;
6060
private HandlerThread mHandlerThread;
61-
private boolean isUpdate=true;
61+
private boolean isUpdate = true;
62+
6263
@Override
6364
protected void onCreate(Bundle savedInstanceState) {
6465
super.onCreate(savedInstanceState);
6566
setContentView(R.layout.activity_main);
6667
mTv = (TextView) findViewById(R.id.tv);
6768
initHandlerThread();
6869
}
70+
6971
private void initHandlerThread() {
7072
mHandlerThread = new HandlerThread("xujun");
7173
mHandlerThread.start();
7274
mThreadHandler = new Handler(mHandlerThread.getLooper()) {
7375
@Override
7476
public void handleMessage(Message msg) {
7577
checkForUpdate();
76-
if(isUpdate){
78+
if (isUpdate) {
7779
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
7880
}
7981
}
8082
};
8183
}
84+
8285
/**
8386
* 模拟从服务器解析数据
8487
*/
@@ -98,18 +101,21 @@ public class MainActivity extends AppCompatActivity {
98101
e.printStackTrace();
99102
}
100103
}
104+
101105
@Override
102106
protected void onResume() {
103-
isUpdate=true;
107+
isUpdate = true;
104108
super.onResume();
105109
mThreadHandler.sendEmptyMessage(MSG_UPDATE_INFO);
106110
}
111+
107112
@Override
108113
protected void onPause() {
109114
super.onPause();
110-
isUpdate=false;
115+
isUpdate = false;
111116
mThreadHandler.removeMessages(MSG_UPDATE_INFO);
112117
}
118+
113119
@Override
114120
protected void onDestroy() {
115121
super.onDestroy();
@@ -127,27 +133,31 @@ public class MainActivity extends AppCompatActivity {
127133

128134
## HandlerThread源码分析
129135

130-
官方源代码如下,是基于sdk23的,可以看到,只有一百多行代码而已
136+
官方源代码如下,是基于sdk23的,可以看到,只有一百多行代码而已
131137

132138
```java
133139
public class HandlerThread extends Thread {
134140
int mPriority;
135141
int mTid = -1;
136142
Looper mLooper;
143+
137144
public HandlerThread(String name) {
138145
super(name);
139146
mPriority = Process.THREAD_PRIORITY_DEFAULT;
140147
}
148+
141149
public HandlerThread(String name, int priority) {
142150
super(name);
143151
mPriority = priority;
144152
}
153+
145154
/**
146155
* Call back method that can be explicitly overridden if needed to execute some
147156
* setup before Looper loops.
148157
*/
149158
protected void onLooperPrepared() {
150159
}
160+
151161
@Override
152162
public void run() {
153163
mTid = Process.myTid();
@@ -165,6 +175,7 @@ public class HandlerThread extends Thread {
165175
Looper.loop();
166176
mTid = -1;
167177
}
178+
168179
public Looper getLooper() {
169180
if (!isAlive()) {
170181
return null;
@@ -180,6 +191,7 @@ public class HandlerThread extends Thread {
180191
}
181192
return mLooper;
182193
}
194+
183195
public boolean quit() {
184196
Looper looper = getLooper();
185197
if (looper != null) {
@@ -188,6 +200,7 @@ public class HandlerThread extends Thread {
188200
}
189201
return false;
190202
}
203+
191204
public boolean quitSafely() {
192205
Looper looper = getLooper();
193206
if (looper != null) {
@@ -196,6 +209,7 @@ public class HandlerThread extends Thread {
196209
}
197210
return false;
198211
}
212+
199213
/**
200214
* Returns the identifier of this thread. See Process.myTid().
201215
*/
@@ -208,19 +222,20 @@ public class HandlerThread extends Thread {
208222
### 1)首先我们先来看一下它的构造方法
209223

210224
```java
211-
public HandlerThread(String name) {
212-
super(name);
213-
mPriority = Process.THREAD_PRIORITY_DEFAULT;
214-
}
215-
public HandlerThread(String name, int priority) {
216-
super(name);
217-
mPriority = priority;
218-
}
225+
public HandlerThread(String name) {
226+
super(name);
227+
mPriority = Process.THREAD_PRIORITY_DEFAULT;
228+
}
229+
230+
public HandlerThread(String name, int priority) {
231+
super(name);
232+
mPriority = priority;
233+
}
219234
```
220235

221236
有两个构造方法,一个参数的和两个参数的,name代表当前线程的名称,priority为线程的优先级别
222237

223-
### 2)接着我们来看一下run()方法,在run方法里面我们可以看到我们会初始化一个Looper,并设置线程的优先级别
238+
### 2)接着我们来看一下run()方法,在run方法里面我们可以看到我们会初始化一个Looper,并设置线程的优先级别
224239

225240
```java
226241
public void run() {
@@ -241,7 +256,7 @@ public void run() {
241256
}
242257
```
243258

244-
- 还记得我们前面我们说到使用HandlerThread的时候必须调用start()方法,接着才可以将我们的HandlerThread和我们的handler绑定在一起吗?其实原因就是我们是在run()方法才开始初始化我们的looper,而我们调用HandlerThread的start()方法的时候,线程会交给虚拟机调度,由虚拟机自动调用run方法
259+
- 还记得我们前面我们说到使用HandlerThread的时候必须调用`start()`方法,接着才可以将我们的HandlerThread和我们的handler绑定在一起吗?其实原因就是我们是在`run()`方法才开始初始化我们的looper,而我们调用HandlerThread的`start()`方法的时候,线程会交给虚拟机调度,由虚拟机自动调用run方法
245260

246261
```java
247262
mHandlerThread.start();
@@ -256,7 +271,7 @@ mThreadHandler = new Handler(mHandlerThread.getLooper()) {
256271
};
257272
```
258273

259-
- 这里我们为什么要使用锁机制和notifyAll();,原因我们可以从getLooper()方法中知道
274+
- 这里我们为什么要使用锁机制和`notifyAll()`;,原因我们可以从`getLooper()`方法中知道
260275

261276
```java
262277
public Looper getLooper() {
@@ -302,7 +317,7 @@ public boolean quitSafely() {
302317
}
303318
```
304319

305-
跟踪这两个方法容易知道只两个方法最终都会调用MessageQueue的quit(boolean safe方法
320+
跟踪这两个方法容易知道只两个方法最终都会调用MessageQueue的`quit(boolean safe)`方法
306321

307322
```java
308323
void quit(boolean safe) {
@@ -326,7 +341,7 @@ void quit(boolean safe) {
326341
}
327342
```
328343

329-
不安全的会调用removeAllMessagesLocked();这个方法,我们来看这个方法是怎样处理的,其实就是遍历Message链表,移除所有信息的回调,并重置为null
344+
不安全的会调用`removeAllMessagesLocked();`这个方法,我们来看这个方法是怎样处理的,其实就是遍历Message链表,移除所有信息的回调,并重置为null
330345

331346
```java
332347
private void removeAllMessagesLocked() {
@@ -340,14 +355,14 @@ private void removeAllMessagesLocked() {
340355
}
341356
```
342357

343-
安全地会调用removeAllFutureMessagesLocked();这个方法,它会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。因此说quitSafe()是安全的,而quit()方法是不安全的,因为quit方法不管是否正在处理消息,直接移除所有回调。
358+
安全地会调用`removeAllFutureMessagesLocked();`这个方法,它会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。因此说`quitSafe()`是安全的,`quit()`方法是不安全的,因为quit方法不管是否正在处理消息,直接移除所有回调。
344359

345360
```java
346361
private void removeAllFutureMessagesLocked() {
347362
final long now = SystemClock.uptimeMillis();
348363
Message p = mMessages;
349364
if (p != null) {
350-
//判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有回调
365+
//判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有回调
351366
if (p.when > now) {
352367
removeAllMessagesLocked();
353368
} else {//正在处理的话,等待该消息处理处理完毕再退出该循环

0 commit comments

Comments
 (0)