Android AsyncTask非同步任務,androidasynctask

來源:互聯網
上載者:User

Android AsyncTask非同步任務,androidasynctask
在上一篇文章《Android網路編程之使用HttpClient進行Get方式通訊》中,我們強制直接在UI線程進行網路操作,在實際的應用開發過程中不能這樣做,因為這樣很可能會阻塞UI,影響使用者體驗。為了避免直接在UI線程中進行網路操作,我們可以使用AsyncTask非同步處理網路通訊和UI更新。通過AysncTask可以很容易的啟動後台線程進行網路通訊,然後將結果返回到UI線程中。

AsyncTask是Android提供的輕量級的非同步類,可以直接繼承AsyncTask,在類中實現非同步作業,並提供介面反饋當前非同步執行的程度(可以通過介面實現UI進度更新),最後反饋執行的結果給UI主線程。

AsyncTask是為了方便編寫後台線程與UI線程互動的輔助類,它的內部實現是一個線程池,每個背景工作會提交到線程池中的線程執行,然後通過向UI線程傳遞訊息的方式調用相應的回調方法實現UI介面的更新。AsyncTask類有三個模板參數:Params(傳遞給背景工作的參數類型),Progress(後台計算執行過程中,進度單位(progress units)的類型,也就是背景程式已經執行了百分之幾)和Result(後台執行返回的結果的類型)。

使用AsyncTask最少要重寫以下兩個方法:
1、doInBackground(Params…) 後台執行,比較耗時的操作都可以放在這裡。注意這裡不能直接操作UI。此方法在後台線程執行,完成任務的主要工作,通常需要較長的時間。在執行過程中可以調用publicProgress(Progress…)來更新任務的進度。
2、onPostExecute(Result) 在這裡面可以使用在doInBackground 得到的結果處理操作UI。 此方法在主線程執行,任務執行的結果作為此方法的參數返回 。

使用AsyncTask類,以下是幾條必須遵守的準則:
1、Task的執行個體必須在UI Thread中建立;
2、execute()方法必須在UI Thread中調用;
3、不要手動的調用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)這幾個方法;
4、該Task只能被執行一次,否則多次調用時將會出現異常;

AsyncTask的一般使用步驟:
1、繼承AsyncTask類並至少重寫doInBackground(Params…)和onPostExecute(Result)方法;
2、執行個體化AsyncTask的子類;
3、調用該執行個體的execute()方法以啟動任務。

整個流程:
AsyncTask的整個調用過程都是從execute()方法開始的(主線程中調用),一旦在主線程中調用execute方法,就會調用onPreExecute方法,在這裡可以做一些準備工作,如在介面上顯示一個進度條,或者一些控制項的執行個體化.同樣也可以通過onProgressUpdate方法給使用者一個進度條的顯示更新,增加使用者體驗;最後通過onPostExecute方法,將在doInBackground得到的結果來處理操作UI。doInBackground任務執行的結果作為此方法的參數返回。

下面同樣以彙總資料空氣品質城市空氣PM2.5指數資料介面為例來示範AsyncTask的使用。

執行個體:AsyncTaskDemo
運行效果:


代碼清單:
布局檔案:activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity" >    <LinearLayout         android:layout_width="match_parent"        android:layout_height="wrap_content"         android:orientation="horizontal" >        <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="1"            android:gravity="center"            android:text="城市:"            android:textSize="23sp" />        <EditText             android:id="@+id/city"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_weight="3"            android:inputType="text" />    </LinearLayout>    <Button        android:id="@+id/query"        android:layout_width="match_parent"        android:layout_height="wrap_content"         android:text="查詢"         android:textSize="23sp" />        <TextView        android:id="@+id/result"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>

Java原始碼檔案:MainActivity.java
package com.rainsong.asynctaskdemo;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {    EditText et_city;    Button btn_query;    TextView tv_result;    QueryTask task;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        et_city = (EditText)findViewById(R.id.city);        tv_result = (TextView)findViewById(R.id.result);        btn_query = (Button)findViewById(R.id.query);        btn_query.setOnClickListener(new OnClickListener() {            public void onClick(View view) {                String city = et_city.getText().toString();                if (city.length() < 1) {                    Toast.makeText(MainActivity.this, "請輸入城市名",                            Toast.LENGTH_LONG).show();                    return;                }                task = new QueryTask(MainActivity.this, tv_result);                task.execute(city);            }        });    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.main, menu);        return true;    }}

Java原始碼檔案:QueryTask.java
package com.rainsong.asynctaskdemo;import java.io.IOException;import java.net.URLEncoder;import java.util.ArrayList;import org.apache.http.HttpResponse;import org.apache.http.NameValuePair;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;import android.content.Context;import android.os.AsyncTask;import android.widget.TextView;import android.widget.Toast;public class QueryTask extends AsyncTask<String, Void, String> {    Context context;    TextView tv_result;    private static final String JUHE_URL_ENVIRONMENT_AIR_PM =                                     "http://web.juhe.cn:8080/environment/air/pm";    private static final String JUHE_APPKEY = "你申請的APPKEY值";    public QueryTask(Context context, TextView tv_result) {        // TODO Auto-generated constructor stub        super();        this.context = context;        this.tv_result = tv_result;     }    @Override    protected String doInBackground(String... params) {        String city = params[0];        ArrayList<NameValuePair> headerList = new ArrayList<NameValuePair>();        headerList.add(new BasicNameValuePair("Content-Type", "text/html; charset=utf-8"));        String targetUrl = JUHE_URL_ENVIRONMENT_AIR_PM;        ArrayList<NameValuePair> paramList = new ArrayList<NameValuePair>();        paramList.add(new BasicNameValuePair("key", JUHE_APPKEY));        paramList.add(new BasicNameValuePair("dtype", "json"));        paramList.add(new BasicNameValuePair("city", city));        for (int i = 0; i < paramList.size(); i++) {            NameValuePair nowPair = paramList.get(i);            String value = nowPair.getValue();            try {                value = URLEncoder.encode(value, "UTF-8");            } catch (Exception e) {            }            if (i == 0) {                targetUrl += ("?" + nowPair.getName() + "=" + value);            } else {                targetUrl += ("&" + nowPair.getName() + "=" + value);            }        }        HttpGet httpRequest = new HttpGet(targetUrl);        try {            for (int i = 0; i < headerList.size(); i++) {                httpRequest.addHeader(headerList.get(i).getName(),                                        headerList.get(i).getValue());            }            HttpClient httpClient = new DefaultHttpClient();            HttpResponse httpResponse = httpClient.execute(httpRequest);            if (httpResponse.getStatusLine().getStatusCode() == 200) {                String strResult = EntityUtils.toString(httpResponse.getEntity());                return strResult;            } else {                return null;            }        } catch (IOException e) {            e.printStackTrace();        }        return null;    }    @Override      protected void onPostExecute(String result) {        if (result != null) {            tv_result.setText(result);        } else {            Toast.makeText(context, "查詢失敗",                                    Toast.LENGTH_LONG).show();            tv_result.setText("");        }    }    }


API知識點
public abstract class
AsyncTask
extends Object

android.os.AsyncTask<Params, Progress, Result>

Class Overview
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.

Public Constructors
AsyncTask()
Creates a new asynchronous task.

static void execute(Runnable runnable)
Convenience version of execute(Object) for use with a simple Runnable object.

abstract Result doInBackground(Params... params)
Override this method to perform a computation on a background thread.

void onCancelled(Result result)
Runs on the UI thread after cancel(boolean) is invoked and doInBackground(Object[]) has finished.

void onCancelled()
Applications should preferably override onCancelled(Object).

void onPostExecute(Result result)
Runs on the UI thread after doInBackground(Params...).

void onPreExecute()
Runs on the UI thread before doInBackground(Params...).

void onProgressUpdate(Progress... values)
Runs on the UI thread after publishProgress(Progress...) is invoked.

final void publishProgress(Progress... values)
This method can be invoked from doInBackground(Params...) to publish updates on the UI thread while the background computation is still running.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.