Diary of Duc

Android – HandlerThread

2018-09-26

Lý do

Để biết lý do vì sao dùng HandlerThread, ta đi so sánh Thread với HandlerThread.

* Thread: Khi sử dụng Thread, ta chỉ có thể tạo một instance Thread va chạy nó, nếu muốn chạy nhiều tác vụ, sẽ phải tạo nhiều instance Thread và quá nhiều Thread cùng chạy thì có khả năng ứng dụng sẽ load chậm, vì cpu bị quá tải số luồng có thể xử lý.
* HandlerThread: Khắc phục nhược điểm của Thread, có thể tái sử dụng Thread để tránh gây quá tải Thread.

Cách hoạt động

Ta sẽ có một hàng đợi các Task, một Looper, một Thread. Looper sẽ giữ cho Thread sống và nó sẽ chạy lần lượt qua các Task trong hàng đợi, Task nào được chạy đến thì thực thi Task đó trong Thread và xóa Task đó khỏi hàng đợi, hết Task này thì đến Task khác.

Chú ý:
* Task mà nói ở trên là nhiệm vụ cần thực hiện, nói dễ hơn là đoạn code cần chạy.
* Cần giải phóng Thread vào lúc thích hợp, chẳng hạn như đóng ứng dụng hoặc không thì Thread sẽ chạy mãi mãi.

Tạo HandlerThread

Trong quá trình học, mình thấy có nhiều cách để tạo và sử dụng HandlerThread, nhưng có một cách mình rất thích vì nó đơn giản và ngắn ngọn, chính là cách này:

Khi Looper gặpTask` đó nó sẽ được thực thi.

1
2
3
val handlerThread = HandlerThread("handlerThread")
handlerThread.start()
val handler = Handler(handlerThread.looper)

* HandlerThread() là một class base từ Thread(), nhưng nó có phương thức looper, chứa hàng đợi Task .
* Handler là một class có nhiệm vụ gửi các Task tới hàng đợi Task của Thread từ Thread khác (UI Thread chẳng hạn)

Post một Task tới hàng đợi

Để post một Task tới hàng đợi, chỉ việc:

1
2
3
handler.post{
// code here
}

Giải phóng Thread

Để giải phóng Thread, chỉ việc:

1
2
handler.removeCallbacks(handlerThread)
handlerThread.quit()

Viết App

Một app đơn giản sử dụng HandlerThread:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
class MainActivity : AppCompatActivity() {

private lateinit var handlerThread: HandlerThread
private lateinit var handler: Handler
private var resumeCountLoad = 0

private fun startHandlerThread(){
handlerThread = HandlerThread("handlerThread")
handlerThread.start()
handler = Handler(handlerThread.looper)
}

private fun cancelHandlerThread(){
handler.removeCallbacks(handlerThread)
handlerThread.quit()
}

private fun postTaskToHandlerThread(){
handler.post{
runOnUiThread {
Toast.makeText(this, "First post from HandlerThread", Toast.LENGTH_SHORT).show()
}
}
handler.post{
val length = 3000000000
for (i in 0 until length){
if (i == length-1){
runOnUiThread {
text_view.text = "Loaded" /* text_view is a Id */
Toast.makeText(this, "Second post from HandlerThread", Toast.LENGTH_SHORT).show()
}
}
}
}
}

override fun onResume() {
super.onResume()
resumeCountLoad++
if (resumeCountLoad > 1)
startHandlerThread()
}

override fun onPause() {
super.onPause()
cancelHandlerThread()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startHandlerThread()
postTaskToHandlerThread()
}
}

Tags: android

URL QR