Android多執行緒理解
Android 理解多執行緒
安卓應用程式通常是應用在一個單獨的執行緒裡的,即為主執行緒,用於顯示使用者介面以及響應使用者的操作。
如果一些耗時任務也同時在主執行緒裡去完成,則會影響使用者體驗,會阻塞UI主執行緒。我們會建立一個單獨的執行緒或者子執行緒,去處理這些耗時操作(如網路請求、資料庫操作等)。
那麼這些子執行緒就是AsyncTask、Thread、HandlerThread,它們叫做安卓的工作者執行緒。
- AsyncTask
- Handler
一、AsyncTask非同步任務
AsyncTask是Android的一個輕量級非同步類,可以自定義類並繼承AsyncTask,實現非同步任務處理操作。並且AsyncTask提供了介面返回非同步操作的進度,最後會返回結果到UI主執行緒中。
優點:簡單快捷,過程可以控制
缺點:在處理多個非同步操作時比較複雜
引數 | 說明 |
---|---|
Params | 啟動任務時輸入的執行引數,一般為一個網路地址 |
Progress | 非同步任務執行的進度 |
Result | 非同步任務執行後的結果的型別 |
程式碼例項
這是一個利用AsyncTask載入網路圖片的程式碼:
public class MainActivity extends ActionBarActivity
{
private Button button1;
private ImageView imageview1;
private ProgressDialog dialog;private String image_uri =”https://imgsa.baidu.com/baike/c0%3Dbaike272%2C5%2C5%2C272%2C90/sign=c4f298bb97ef76c6c4dff379fc7f969f/9358d109b3de9c82f077b3156b81800a19d8431d.jpg”;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dialog = new ProgressDialog(this);
dialog.setTitle(“圖片下載”);
dialog.setMessage(“正在下載,請稍後…”);
button1 = (Button) findViewById(R.id.button1);
imageview1 = (ImageView) findViewById(R.id.imageView1);
button1.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
new DownloadTask().execute(image_uri);
}
});
}
//自定義下載類繼承AsyncTask
public class DownloadTask extends AsyncTask<String, Void, Bitmap>
{
// 這個方法會在後臺任務開始執行之間呼叫,用於進行一些介面上的初始化操作,比如顯示一個進度條對話方塊等。
@Override
protected void onPreExecute()
{
// TODO Auto-generated method stub
dialog.show();
super.onPreExecute();
}
// 這個方法中的所有程式碼都會在子執行緒中執行,主要完成耗時任務
// 注意,在這個方法中是不可以進行UI操作的
//在執行過程中可以呼叫publishProgress(Progress... values)來更新進度資訊。
@Override
protected Bitmap doInBackground(String... params)
{
// TODO Auto-generated method stub
// 使用網路連結類HttpClient完成網路資料的獲取
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(params[0]);
Bitmap bitmap = null;
try
{
HttpResponse httpResponse = httpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() == 200)
{
HttpEntity httpEntity = httpResponse.getEntity();
byte[] data = EntityUtils.toByteArray(httpEntity);
bitmap = BitmapFactory
.decodeByteArray(data, 0, data.length);
}
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
return bitmap;
}
//在呼叫publishProgress(Progress... values)時,此方法被執行,直接將進度資訊更新到UI元件上。
@Override
protected void onProgressUpdate(Void... values)
{
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
// 可以利用返回的資料來進行一些UI操作,比如說提醒任務執行的結果,以及關閉掉進度條對話方塊等。
protected void onPostExecute(Bitmap result)
{
// TODO Auto-generated method stub
super.onPostExecute(result);
imageview1.setImageBitmap(result);
dialog.dismiss();
}
}
}
參考:android AsyncTask介紹
詳解Android中AsyncTask的使用
二、Handler
1、Handler概念:
I 、Handler 是 Android 給我們提供來更新 UI 的一套機制,也是一套訊息處理的機制,我們可以傳送訊息,也可以通過它來處理訊息。
II、Android 在設計的時候,就封裝了一套訊息建立、傳遞、處理機制,如果不遵循這樣的機制就沒有辦法更新 UI 資訊,就會丟擲異常資訊。
2、與Handler相關的幾個概念:
I、Message 訊息,理解為執行緒間通訊的資料單元。例如後臺執行緒在處理資料完畢後需要更新UI,則可傳送一條包含更新資訊的Message給UI執行緒。
II、Message Queue 訊息佇列,用來存放通過Handler釋出的訊息,按照先進先出執行。
III、Handler Handler是Message的主要處理者,負責將Message新增到訊息佇列以及對訊息佇列中的Message進行處理。
Looper 迴圈器,扮演Message Queue和Handler之間橋樑的角色,迴圈取出Message Queue裡面的Message,並交付給相應的Handler進行處理。
IV、執行緒 UI thread 通常就是main thread,而Android啟動程式時會替它建立一個Message Queue。每一個執行緒裡可含有一個Looper物件以及一個MessageQueue資料結構。在你的應用程式裡,可以定義Handler的子類別來接收Looper所送出的訊息。
3、Handler的一些分發訊息的方法
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
4、關於Message
建立Handler例項,要過載handleMessage方法,來處理訊息
獲取Message物件的最好方法是呼叫Message.obtain()
Message可傳遞的引數:
①. arg1 arg2 整數型別,是setData的低成本替代品,傳遞簡單型別。
Object 型別 obj
②. what 使用者自定義的訊息程式碼,這樣接受者可以瞭解這個訊息的資訊。每個handler各自包含自己的訊息程式碼,所以不用擔心自定義的訊息跟其他handlers有衝突
③.其他的可以通過Bundle進行傳遞
Message可以通過new Message構造來建立一個新的Message,但是這種方式很不好,不建議使用。最好使用Message.obtain()來獲取Message例項,它建立了訊息池來處理的。
5、程式碼例項
利用Handler建立一個dialog進度條並顯示進度
public class HandlerActivity extends Activity
{
private Button button1;
private static ProgressDialog dialog;
//建立Handler靜態物件
private static Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
int index=msg.arg1;
dialog.setProgress(index);
if (msg.what==1)
{
dialog.dismiss();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
button1=(Button)findViewById(R.id.button1);
dialog=new ProgressDialog(this);
dialog.setTitle(“正在下載…”);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
button1.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// TODO Auto-generated method stub
new Thread(new MyThread()).start();
dialog.show();
}
});
}
//建立一個子執行緒繼承Runnable
public class MyThread implements Runnable{
int count=1;
int index=0;
@Override
public void run()
{
// TODO Auto-generated method stub
while(count<=100){
try
{
Thread.sleep(200);
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
Message message=Message.obtain();
message.arg1=count;
handler.sendMessage(message);
count++;
}
Message end=Message.obtain();
end.what=1;
handler.sendMessage(end);
}
}