1
- ** 我们知道在Android系统中,我们执行完耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁。想象一下如果我们在项目中经常要执行耗时操作,如果经常要开启线程,接着又销毁线程,这无疑是很消耗性能的? 那有什么解决方法呢?**
1
+ ** 我们知道在Android系统中,我们执行完耗时操作都要另外开启子线程来执行,执行完线程以后线程会自动销毁。想象一下如果我们在项目中经常要执行耗时操作,如果经常要开启线程,接着又销毁线程,这无疑是很消耗性能的? 那有什么解决方法呢?**
2
2
3
3
1 . 使用线程池
4
4
2 . 使用HandlerThread
12
12
13
13
### 使用场景
14
14
15
- HandlerThread是Google帮我们封装好的,可以用来执行多个耗时操作,而不需要多次开启线程,里面是采用handler和Looper实现的
15
+ HandlerThread是Google帮我们封装好的,可以用来执行多个耗时操作,而不需要多次开启线程,里面是采用Handler和Looper实现的。
16
16
17
17
> 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.
18
18
@@ -35,7 +35,7 @@ handlerThread.start();
35
35
1 . 将我们的handlerThread与Handler绑定在一起。
36
36
还记得是怎样将Handler与线程对象绑定在一起的吗?其实很简单,就是将线程的looper与Handler绑定在一起,代码如下:
37
37
38
- ``` java
38
+ ``` java
39
39
mThreadHandler = new Handler (mHandlerThread. getLooper()) {
40
40
@Override
41
41
public void handleMessage (Message msg ) {
@@ -51,34 +51,37 @@ mThreadHandler = new Handler(mHandlerThread.getLooper()) {
51
51
52
52
### 完整测试代码如下
53
53
54
- ``` java
54
+ ``` java
55
55
public class MainActivity extends AppCompatActivity {
56
- private TextView mTv ;
56
+ private static final int MSG_UPDATE_INFO = 0x100 ;
57
57
Handler mMainHandler = new Handler ();
58
+ private TextView mTv;
58
59
private Handler mThreadHandler;
59
- private static final int MSG_UPDATE_INFO = 0x100 ;
60
60
private HandlerThread mHandlerThread;
61
- private boolean isUpdate= true ;
61
+ private boolean isUpdate = true ;
62
+
62
63
@Override
63
64
protected void onCreate (Bundle savedInstanceState ) {
64
65
super . onCreate(savedInstanceState);
65
66
setContentView(R . layout. activity_main);
66
67
mTv = (TextView ) findViewById(R . id. tv);
67
68
initHandlerThread();
68
69
}
70
+
69
71
private void initHandlerThread () {
70
72
mHandlerThread = new HandlerThread (" xujun" );
71
73
mHandlerThread. start();
72
74
mThreadHandler = new Handler (mHandlerThread. getLooper()) {
73
75
@Override
74
76
public void handleMessage (Message msg ) {
75
77
checkForUpdate();
76
- if (isUpdate){
78
+ if (isUpdate) {
77
79
mThreadHandler. sendEmptyMessage(MSG_UPDATE_INFO );
78
80
}
79
81
}
80
82
};
81
83
}
84
+
82
85
/**
83
86
* 模拟从服务器解析数据
84
87
*/
@@ -98,18 +101,21 @@ public class MainActivity extends AppCompatActivity {
98
101
e. printStackTrace();
99
102
}
100
103
}
104
+
101
105
@Override
102
106
protected void onResume () {
103
- isUpdate= true ;
107
+ isUpdate = true ;
104
108
super . onResume();
105
109
mThreadHandler. sendEmptyMessage(MSG_UPDATE_INFO );
106
110
}
111
+
107
112
@Override
108
113
protected void onPause () {
109
114
super . onPause();
110
- isUpdate= false ;
115
+ isUpdate = false ;
111
116
mThreadHandler. removeMessages(MSG_UPDATE_INFO );
112
117
}
118
+
113
119
@Override
114
120
protected void onDestroy () {
115
121
super . onDestroy();
@@ -127,27 +133,31 @@ public class MainActivity extends AppCompatActivity {
127
133
128
134
## HandlerThread源码分析
129
135
130
- 官方源代码如下,是基于sdk23的,可以看到,只有一百多行代码而已
136
+ 官方源代码如下,是基于sdk23的,可以看到,只有一百多行代码而已。
131
137
132
138
``` java
133
139
public class HandlerThread extends Thread {
134
140
int mPriority;
135
141
int mTid = - 1 ;
136
142
Looper mLooper;
143
+
137
144
public HandlerThread (String name ) {
138
145
super (name);
139
146
mPriority = Process . THREAD_PRIORITY_DEFAULT ;
140
147
}
148
+
141
149
public HandlerThread (String name , int priority ) {
142
150
super (name);
143
151
mPriority = priority;
144
152
}
153
+
145
154
/**
146
155
* Call back method that can be explicitly overridden if needed to execute some
147
156
* setup before Looper loops.
148
157
*/
149
158
protected void onLooperPrepared () {
150
159
}
160
+
151
161
@Override
152
162
public void run () {
153
163
mTid = Process . myTid();
@@ -165,6 +175,7 @@ public class HandlerThread extends Thread {
165
175
Looper . loop();
166
176
mTid = - 1 ;
167
177
}
178
+
168
179
public Looper getLooper () {
169
180
if (! isAlive()) {
170
181
return null ;
@@ -180,6 +191,7 @@ public class HandlerThread extends Thread {
180
191
}
181
192
return mLooper;
182
193
}
194
+
183
195
public boolean quit () {
184
196
Looper looper = getLooper();
185
197
if (looper != null ) {
@@ -188,6 +200,7 @@ public class HandlerThread extends Thread {
188
200
}
189
201
return false ;
190
202
}
203
+
191
204
public boolean quitSafely () {
192
205
Looper looper = getLooper();
193
206
if (looper != null ) {
@@ -196,6 +209,7 @@ public class HandlerThread extends Thread {
196
209
}
197
210
return false ;
198
211
}
212
+
199
213
/**
200
214
* Returns the identifier of this thread. See Process.myTid().
201
215
*/
@@ -208,19 +222,20 @@ public class HandlerThread extends Thread {
208
222
### 1)首先我们先来看一下它的构造方法
209
223
210
224
``` 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
+ }
219
234
```
220
235
221
236
有两个构造方法,一个参数的和两个参数的,name代表当前线程的名称,priority为线程的优先级别
222
237
223
- ### 2)接着我们来看一下run() 方法,在run方法里面我们可以看到我们会初始化一个Looper,并设置线程的优先级别
238
+ ### 2)接着我们来看一下run() 方法,在run方法里面我们可以看到我们会初始化一个Looper,并设置线程的优先级别
224
239
225
240
``` java
226
241
public void run() {
@@ -241,7 +256,7 @@ public void run() {
241
256
}
242
257
```
243
258
244
- - 还记得我们前面我们说到使用HandlerThread的时候必须调用start() 方法,接着才可以将我们的HandlerThread和我们的handler绑定在一起吗?其实原因就是我们是在run() 方法才开始初始化我们的looper,而我们调用HandlerThread的start() 方法的时候,线程会交给虚拟机调度,由虚拟机自动调用run方法
259
+ - 还记得我们前面我们说到使用HandlerThread的时候必须调用 ` start() ` 方法,接着才可以将我们的HandlerThread和我们的handler绑定在一起吗?其实原因就是我们是在 ` run() ` 方法才开始初始化我们的looper,而我们调用HandlerThread的 ` start() ` 方法的时候,线程会交给虚拟机调度,由虚拟机自动调用run方法:
245
260
246
261
``` java
247
262
mHandlerThread. start();
@@ -256,7 +271,7 @@ mThreadHandler = new Handler(mHandlerThread.getLooper()) {
256
271
};
257
272
```
258
273
259
- - 这里我们为什么要使用锁机制和notifyAll();,原因我们可以从getLooper() 方法中知道
274
+ - 这里我们为什么要使用锁机制和 ` notifyAll() ` ;,原因我们可以从 ` getLooper() ` 方法中知道
260
275
261
276
``` java
262
277
public Looper getLooper() {
@@ -302,7 +317,7 @@ public boolean quitSafely() {
302
317
}
303
318
```
304
319
305
- 跟踪这两个方法容易知道只两个方法最终都会调用MessageQueue的quit( boolean safe) 方法
320
+ 跟踪这两个方法容易知道只两个方法最终都会调用MessageQueue的 ` quit( boolean safe) ` 方法
306
321
307
322
``` java
308
323
void quit(boolean safe) {
@@ -326,7 +341,7 @@ void quit(boolean safe) {
326
341
}
327
342
```
328
343
329
- 不安全的会调用removeAllMessagesLocked ();这个方法,我们来看这个方法是怎样处理的,其实就是遍历Message链表,移除所有信息的回调,并重置为null
344
+ 不安全的会调用 ` removeAllMessagesLocked ();` 这个方法,我们来看这个方法是怎样处理的,其实就是遍历Message链表,移除所有信息的回调,并重置为null。
330
345
331
346
``` java
332
347
private void removeAllMessagesLocked() {
@@ -340,14 +355,14 @@ private void removeAllMessagesLocked() {
340
355
}
341
356
```
342
357
343
- 安全地会调用removeAllFutureMessagesLocked ();这个方法,它会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。因此说quitSafe() 是安全的,而quit() 方法是不安全的,因为quit方法不管是否正在处理消息,直接移除所有回调。
358
+ 安全地会调用 ` removeAllFutureMessagesLocked ();` 这个方法,它会根据Message.when这个属性,判断我们当前消息队列是否正在处理消息,没有正在处理消息的话,直接移除所有回调,正在处理的话,等待该消息处理处理完毕再退出该循环。因此说 ` quitSafe() ` 是安全的,而 ` quit() ` 方法是不安全的,因为quit方法不管是否正在处理消息,直接移除所有回调。
344
359
345
360
``` java
346
361
private void removeAllFutureMessagesLocked() {
347
362
final long now = SystemClock . uptimeMillis();
348
363
Message p = mMessages;
349
364
if (p != null ) {
350
- // 判断当前队列中的消息是否正在处理这个消息,》 没有的话,直接移除所有回调
365
+ // 判断当前队列中的消息是否正在处理这个消息,没有的话,直接移除所有回调
351
366
if (p. when > now) {
352
367
removeAllMessagesLocked();
353
368
} else {// 正在处理的话,等待该消息处理处理完毕再退出该循环
0 commit comments