Android中執行緒按功能分的話,可以分為兩個,一個是主執行緒(UI執行緒),其他的都是子執行緒
主執行緒不能執行那些耗時過長的代碼或任務(執行耗時過長的代碼會出現應用未回應的提示),所以都是使用子執行緒來執行耗時過長的代碼,比如說下載檔案等任務
一般情況,子執行緒中執行過長的代碼,都是需要進行更新UI操作,
但是Android中,為了防止安全,是不允許在子執行緒更新UI的,但是我們可以使用到Android官方給予的API來實作子執行緒更新UI的操作(本質上,這些API也是切換回了主執行緒來進行更新UI)
例子:點擊一個按鈕,過了1s后完成了下載任務,回傳了資料,此資料會顯示在界面上

具體解釋:
點擊按鈕,之后開啟一個子執行緒來模擬下載程序(執行緒休眠1s),之后任務執行完畢會回傳資料(一個String),使用回傳的資料更新UI
新建一個方法,用來模擬下載任務
/**
* 模擬下載
*/
fun download(): String {
Thread.sleep(1000)
return "this is data"
}
下面的使用6種方式和上面的模擬下載任務的方法,來實作上面例子的效果
1.Activity.runOnUiThread()
runOnUiThread是Activity中的方法,只有當前物件是Activity,就可以直接使用,如果當前的物件不是Activity,需要找到Activity物件,才能執行此方法
runOnUiThread方法的引數為一個Runnable介面,我使用的kotlin,所以有很多東西都是省略了
設定按鈕的點擊事件,點擊按鈕開啟一個執行緒
btn_start.setOnClickListener {
thread {
val data = https://www.cnblogs.com/stars-one/p/download()
runOnUiThread({
//這里進行更新UI操作
tv_show.text = data
})
}
}
Java版
btn_start.setOnClickListener(new OnClickListener(){
new Thread(new Runnable(){
String data = https://www.cnblogs.com/stars-one/p/download();
runOnUiThread(new Runnable(){
@Override
public void run() {
tv_show.setText(data);
}
})
}).start();
});
2.View.post()
post方法是View物件的方法,引數也是接收一個runnable介面
這里我選用的view物件是需要進行更新textview的本身,當然也可以選用其他的View物件,只要是在當前Activity的物件都可以
btn_start.setOnClickListener {
thread {
val data = https://www.cnblogs.com/stars-one/p/download()
//選擇當前Activity的View物件都可以
tv_show.post {
tv_show.text = data
}
}
}
3.View.PostDelayed()
此方法和上面的post方法類似,只是多一個引數,用來實作延遲更新UI的效果
btn_start.setOnClickListener {
thread {
val data = https://www.cnblogs.com/stars-one/p/download()
tv_show.postDelayed({
tv_show.text = data
},2000)
}
}
上面的代碼實作的效果是點擊按鈕之后,過了3s后才會看到界面發生改變
4.Handler.post()
new一個Handler物件(全域變數)
private val handler = Handler()
使用post方法更新UI,此post方法和之前的post方法一樣,引數都是為Runnable介面
btn_start.setOnClickListener {
thread {
val data = https://www.cnblogs.com/stars-one/p/download()
handler.post {
tv_show.text = data
}
}
}
5.AsyncTask(推薦)
說明
AsyncTask是一個抽象類,必須創建一個子類類繼承它
這里介紹一下關于AsyncTask的三個泛型引數和幾個方法
泛型引數可以為任意型別,為空的話使用Void
| 引數 | 說明 |
|---|---|
| params | 引數泛型,doInBackground方法的引數 |
| progress | 進度泛型,onProgressUpdate方法的引數 |
| result | 結果泛型,onPostExecute方法的引數 |
抽象方法說明:
| 方法名 | 說明 |
|---|---|
| onPreExectute() | 此方法中,常常進行初始化操作,如進度條顯示 |
| doInBackground(Params...) | 此方法必須實作, |
| onProgressUpdate(Progress...) | 進行更新UI的操作 |
| publishProgress(Progress...) | 在doInBackground方法中呼叫,呼叫此方法后會回呼執行onProgressUpdate方法進行更新UI |
| onPostExcute(Result) | 任務結束之后進行更新UI |
簡單來說,如果子類繼承了AsyncTask,它的抽象方法的引數都會變成泛型對應的型別
例子
下面的代碼是取自我的APP,簡單地說明一下AsyncTask<String, DownloadingItem, DownloadedItem>
我傳入的是3個泛型引數分別為String,DownloadingItem,DownloadedItem,分別對應的params,progress和result泛型
這里我是根據自己的需要而兩個類DownloadingItem和DownloadedItem,從下面的代碼可以看到,抽象方法的引數變為了我們的泛型的型別
internal inner class DownloadingTask : AsyncTask<String, DownloadingItem, DownloadedItem>() {
override fun onPreExecute() {
//一些初始化操作
}
override fun doInBackground(vararg params: String?): DownloadedItem {
//params是一個引數陣列,如果創建DownloadingTask物件只傳入了一個引數,直接取下標為0的那個即可(需要轉型)
//耗時操作(如下載操作),獲得進度資料
//將新的進度資料傳遞到onProgressUpdate方法,更新UI
publishProgress(messageItem)
//任務執行完畢,回傳結果(回呼onPostExecute方法)
}
override fun onProgressUpdate(vararg values: DownloadingItem?) {
//這里使用最新的進度來進行相關UI的更新
//values是一個DownloadingItem陣列,取末尾那個即為最新的進度資料
}
override fun onPostExecute(result: DownloadedItem?) {
//下載成功提示或者是其他更新UI的操作
}
}
執行:
執行Task的時候需要在主執行緒(UI執行緒呼叫)
DownloadingTask().execute("引數")
批量下載:
//允許在同一時刻有5個任務正在執行,并且最多能夠存盤50個任務
private val exec = ThreadPoolExecutor(5, 50, 10, TimeUnit.SECONDS, LinkedBlockingQueue<Runnable>())
DownloadingTask().executeOnExecutor(exec, url)
6.Handler機制實作(核心)
其實,Handler機制是子行程更新UI的核心
我們上面的五種實作子行程更新UI的方式,都是基于Handler機制實作的

具體機制本文就不多說了,網上有許多的機制說明,這里就只講一下實作的步驟
Message中有幾個屬性,what,arg1,arg2,這三個都是接收一個Int,所以,傳遞資料不是很友好,這里就不準備實作之前的例子效果了
what表示來源,arg1和arg2用來傳遞Int資料
1.重寫Handler類中的handleMessage方法
一般都是規定好一個Int的常量,來表示what
private val handler =object : Handler(){
override fun handleMessage(msg: Message?) {
if (msg.what == 1) {
//來源為1,則
}
}
}
2.發送Message
val msg = handler.obtainMessage()
//一般都是規定好一個Int的常量,來表示what
msg.what = 1
//傳遞Int資料
msg.arg1 = 20
handler.sendMessage(msg)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/55646.html
標籤:Android
