線程的基本用法:
定義一個線程只需要新建一個類繼承自Thread,然后重新父類的run()方法,并在里面編寫耗時邏輯即可
class MyThread extends Thread{
@Override
public void run(){
//處理具體的邏輯
}
}
然后啟用這個線程,只需要調(diào)用該類的start方法即可:
new MyThread().start()
但是使用繼承的方式耦合性有點高,更多時候選擇使用實現(xiàn)Runable接口的方式來定義一個線程
class MyThread implemens Runnable {
@Override
public void run(){
//處理具體邏輯
}
}
使用這種寫法,啟動線程是:
MyThread myThread = new MyThread();
new Thread(myThread).start();
Android是不允許在子線程中進行UI操作的,我們可以利用Android提供的異步消息機制,來解決在子線程中進行UI操作的問題。
public class MainActivity extends AppCompatActivity {
public static final int UPDATE_TEXT = 1;
private TextView text;
//消息接收處理的handler
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_TEXT:
Log.d("MainActivity","test");
//在這里進行UI操作
Log.d("MainActivity",""+msg.arg1);
text.setText("Nice to meet you");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.text);
Button changeText = (Button)findViewById(R.id.change_text);
changeText.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
//在子線程里發(fā)送更新文字的message
Message message = new Message();
message.what = UPDATE_TEXT;
message.arg1 = 1;
handler.sendMessage(message);
}
}).start();
}
});
}
}
解析異步消息處理機制:
Android的異步消息處理主要由4個部分組成:Message、Handler、MessageQueue和Looper
- Message
Message 是在線程之間傳遞的消息,可在內(nèi)部攜帶少量的信息,用于不同線程之間交換數(shù)據(jù)。
有what、arg1、arg2來攜帶一些整形數(shù)據(jù),使用obj字段攜帶一個Object對象 - Handler
Handler 顧名思義也就是處理者的意思,它主要是用于發(fā)送和處理消息。
發(fā)送消息一般使用Handler的sendMessage()方法;處理消息使用Handler的 handleMessage()方法 - MessageQueue
MessageQueue是消息隊列的意思,它主要是用于存放所有通過Handler發(fā)送的消息。這部分消息會一直存放在消息隊列中,等待被處理。每個線程中只會有一個Message對象。 - Looper
Looper是每個線程中的MessageQueue的管家,調(diào)用Looper的loop()方法后,就會進入到一個無線循環(huán)當(dāng)中,然后每當(dāng)發(fā)現(xiàn)MessageQueue中存在一條消息,就會將它取出,并傳遞到Handler的handleMessage()方法當(dāng)中

使用AsyncTask
由于AsyncTask是一個抽象類,所以要使用它,就必須創(chuàng)建一個子類去繼承它。在繼承時,可以為AsyncTask類指定3個泛型參數(shù),這3個參數(shù)的用途如下:
- Params
在執(zhí)行AsyncTask時需要傳入的參數(shù),可用于在后臺任務(wù)中使用 - Progress
后臺任務(wù)執(zhí)行時,如果需要在界面上顯示當(dāng)前進度,則使用這里指定的泛型作為進度單位 - Result
當(dāng)任務(wù)執(zhí)行完畢后,如果需要對結(jié)果進行返回,則使用這里指定的泛型作為返回值類型
使用AsyncTask還經(jīng)常需要重寫以下4個方法:
onPreExecute()
在后臺任務(wù)開始執(zhí)行之前調(diào)用,用于進行一些界面上的初始化操作,比如顯示一個進度條對話框doInBackground(Params...)
這個方法中所有的代碼都在子線程執(zhí)行,應(yīng)該在這里處理所有的耗時任務(wù)。在這個方法中是不能進行UI操作的,只能調(diào)用publishProgress(Progress...)方法將數(shù)值傳遞出去,并觸發(fā) onProgressUpdate(Progress...)方法onProgressUpdate(Progress...)
當(dāng)在后臺任務(wù)中調(diào)用了publishProgress(Progress...)方法后,onProgressUpdate(Progress...)方法就會很快被調(diào)用,該方法中攜帶的參數(shù)就是在后臺任務(wù)中傳遞過來的,在這個方法中可以對UI進行操作。-
onPostExecute(Result)
后臺任務(wù)執(zhí)行完畢并通過return語句進行返回時,這個方法就很快被調(diào)用,返回的數(shù)據(jù)就會作為參數(shù)傳遞到此方法之中,可以利用返回的數(shù)據(jù)來進行一些UI操作。public class DownloadTask extends AsyncTask<Void,Integer,Boolean> {
ProgressDialog progressDialog = new ProgressDialog();@Override protected void onPreExecute() { progressDialog.show(); //顯示進度對話框 } @Override protected Boolean doInBackground(Void... params) { try { while (true) { int downloadPercent = doDownload(); //此處調(diào)用publishProgress()方法,會觸發(fā) onProgressUpdate()方法 publishProgress(downloadPercent); if (downloadPercent >= 100) { break; } } }catch(Exception e){ return false; } return true; } } @Override protected void onProgressUpdate(Integer... values) { //在這里進行UI操作,更新進度條 progressDialog.setMessage("Downloaded " + values[0] + "%"); } @Override protected void onPostExecute(Boolean result) { progressDialog.dismiss(); //在這里提示下載結(jié)果 if(result) { Toast.makeText(context, "Download successed", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(context, "Download faild", Toast.LENGTH_SHORT).show(); } }}
啟用這個任務(wù),只需要
new DownloadTask().execute();
簡單來說,使用AsyncTask的訣竅就是,在onPreExecute()方法中進行初始化工作,在doInBackground()方法中執(zhí)行具體的耗時任務(wù),在onProgressUpdate()方法中進行UI操作,在onPostExecute()方法中執(zhí)行一些任務(wù)的收尾工作。
而調(diào)用publishProgress()方法,能夠?qū)?shù)據(jù)從后臺傳遞到主線程,觸發(fā)onProgressUpdate(Progress...)方法