Android編程:用AsyncTask實現多線程




內容簡介


1、前言

2、AsyncTask介紹

3、實例

4、總結



前言


目前有一個微信羣和一個QQ羣,凡是對編程感興趣的朋友可以加,大家可以交流,學習,互動,分享寫的程序的源代碼,等。

微信羣(程序員聯盟)目前近80人了,加羣請聯繫我。

QQ羣(程序員聯盟),羣號是 413981577

QQ羣共享裏有N多編程PDF。

我們還建立了一個公共的百度雲盤,2TB容量,供大家上傳優秀編程資源,賬號和密碼加羣之後會發送。

我的微信號可以在文章最後看到,QQ和郵箱也在最後。

也創建了《程序員聯盟》的微社區,方便大家提問和互動。可以關注一下。

微社區地址和二維碼如下:

http://m.wsq.qq.com/264152148

在Android應用開發中,有時我們需要實現任務的同步。Android裏的AsyncTask類可以幫我們更好地管理線程同步(異步方式),就像Thread類能做的,不過用法比Thread更簡單。




AsyncTask介紹


在你開發Android應用程序時,如果在一個Activity裏有一個耗時任務(通常是一個子線程),並且這個任務調用/操作了主線程,應用就會拋出著名的“ANR” (Application Not Responding)錯誤。


Figure 1: ANR


AsyncTask類可以幫我們解圍,使用AsyncTask能讓我們正確及簡便地使用主線程,即使此時另有一個異步線程被創建。它使得耗時任務可以在後臺執行,並在前臺(UI線程或主線程)把執行結果展現出來,不必用到Thread類或Handler類。線程間通信也隨之變得更簡單,優雅。


* 主線程(User Interface Thread UI線程)是在Android裏負責和用戶界面進行交互的線程。


AsyncTask是一個抽象類,必須被繼承才能實例化。有三個泛型參數,分別是: Params, ProgressResult


- Params : 傳遞給執行的任務的參數,也就是doInBackground方法的參數。


- Progress : 後臺任務執行過程中在主線程展現更新時傳入的參數,也就是onProgressUpdate方法的參數。


- Result : 後臺執行的任務返回的結果,也就是onPostExecute方法的參數。


除此之外,繼承AsyncTask類時,一般需要實現四個方法。當然應用程序不需要調用這些方法,這些方法會在任務執行過程中被自動調用: onPreExecute, doInBackground, onProgressUpdate 和 onPostExecute (其中的doInBackground抽象方法必須要被子類重寫):


- onPreExecute : 此方法在主線程中執行,用於初始化任務。


- doInBackground : 此方法在後臺執行。此方法在onPreExecute方法執行完後啓動。這個方法中執行的操作可以是耗時的,並不會阻塞主線程。通過調用publishProgress方法來在主線程顯示後臺任務執行的結果更新。


- onProgressUpdate : 此方法也在主線程中執行,每當publishProgress方法被調用時,此方法就被執行,此方法只在doInBackground執行過程中才能被調用。


- onPostExecute : 在doInBackground方法執行完之後啓動的方法,在後臺任務結束後才調用此方法,也在主線程執行。




實例


爲了更好地展現AsyncTask的使用,我們來實現一個計時器的小應用。首先我們創建一個Android項目,就命名爲“AsyncTaskActivity”好了(名字無所謂),修改 res->layout 裏的定義主用戶界面的 xml 文件:


main.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="15dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="5dp"
android:text="Time in min"
android:textSize="18dp"
android:textStyle="bold" />
<EditText
android:id="@+id/chronoValue"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginBottom="15dp"
android:layout_gravity="center"
android:hint="minutes"
android:inputType="number"
android:singleLine="true"
android:text="1"
android:textSize="15dp" />

<TextView
android:id="@+id/chronoText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="0:0"
android:textSize="80dp" />

<Button
android:id="@+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="Start" />

</LinearLayout>


在以上的main.xml文件中,我們主要定義了一個EditText,用於輸入需要計數的時間;一個TextView,用於顯示計數的變化; 和一個Button,用於啓動計數任務。


在我們的類AsyncTaskActivity中,我們首先聲明三個private變量,對應以上三個元素。


private Button start;
private TextView chronoText;
private EditText chronoValue;


然後創建一個內部類,繼承AsyncTask類,命名爲“Chronograph”,就是秒錶或計時器。


private class Chronograph extends AsyncTask<Integer, Integer, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Disable the button and edittext before the start of the deduction
chronoValue.setEnabled(false);
start.setEnabled(false);
chronoText.setText("0:0");
}
@Override
protected Void doInBackground(Integer... params) {
// Deduction
for (int i = 0; i <= params[0]; i++) {
for (int j = 0; j < 60; j++) {
try {
// Publication of increment
publishProgress(i, j);
if (i == params[0]) {
return null;
}
// Pause for one second
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (isCancelled()) {
return null;
}
return null;
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Update on the User Interface
chronoText.setText(values[0] + ":" + values[1]);
}

@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Reactivation of the button and edittext
chronoValue.setEnabled(true);
start.setEnabled(true);
}
}


以上,我們重寫了我們需要的四個方法。最後我們再完成我們AsyncTaskActivity類的onCreate方法:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// Recuperation of the usable components
start = (Button)findViewById(R.id.start);
chronoText = (TextView)findViewById(R.id.chronoText);
chronoValue = (EditText)findViewById(R.id.chronoValue);

start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Recuperation of the value in the EditText
int value = Integer.parseInt(String.valueOf(chronoValue.getText()));
// Verification of the content
if (value > 0) {
new Chronograph().execute(value);
}
else {
Toast.makeText(AsyncTaskActivity.this, "Please enter a correct value !", Toast.LENGTH_LONG).show();
}
}
});
}


如果我們在繼承AsyncTask類時,對於三個參數中有不需要的,可以定義爲Void類型(注意,與小寫的 void 不同),例如:


private class Chronograph extends AsyncTask<Integer, Integer, Void> {...}


運行我們的項目,可以得到如下面三張圖所示的結果:




Figure 2: 按下Start按鈕前





Figure 3: 計數中




Figure 4: 計數後



總結

今後,當有異步任務需要執行時,可以使用AsyncTask類,可以根據自己的需要來定製。


AsyncTask使用了線程池(Thread Pool)的機制,使得同時執行多個AsyncTask成爲可能。但是要注意的是,這個線程池的容量是5個線程同時執行,如果超過了這個數量,多餘的線程必須等待線程池裏的線程執行完才能啓動。


因此,使用AsyncTask,最好在明確知道任務會有一個確定和合理的結束的情況下。否則,還是使用傳統的Thread類爲好。




程序員聯盟 微信公衆號 *您若覺得本文不錯,點擊畫面右上角《···》按鈕“分享到朋友圈或“發送給朋友

*新朋友請關注「程序員聯盟」微信搜公衆號 ProgrammerLeague

小編微信號frogoscar

小編QQ號: 379641629

小編郵箱[email protected]

程序員聯盟QQ羣:413981577

微信和郵箱最常用


PS: 有朋友反映看手機端的文章太累,其實是可以用瀏覽器網頁來看的

方法1. 點擊畫面右上角的《···》按鈕,然後選擇“複製鏈接”,再把鏈接黏貼到你的瀏覽器裏面或用郵件發送給自己,就可以在電腦的瀏覽器裏打開了



方法2. 頭條網www.toutiao.com,搜索我的自媒體“程序員聯盟”,裏面有所有文章,也可以直接進這個鏈接:http://www.toutiao.com/m3750422747/



新朋友如何查看所有文章:

點擊“查看公衆號”,再點擊“查看歷史消息”





程序員聯盟”公衆號專爲程序員,App設計師,各位喜愛編程和熱愛分享的小夥伴們推送各樣編程相關知識,優秀軟件推薦,業界動態等。搜索 ProgrammerLeague 加關注~


持續關注 程序員聯盟 微信公衆號,更多有趣,有料,有亮點的內容等着你哦!



點擊下方 閱讀原文 查看 AsyncTask官方文檔
↓↓↓

本文分享自微信公衆號 - 程序員聯盟(coderhub)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章