Android 異步任務——AsyncTask (附使用AsyncTask下載圖片Demo)

  咱們編程的時候常常須要處理同步任務和異步任務,在Android裏面存在一個特性,就是UI線程是不安全的線程。所謂UI線程不安全也就是咱們的主線程(進程啓動的第一個線程)不能在線程外操做主線程的資源。由於主線程的資源沒有作同步處理。也就是咱們通常說的線程同步問題。html

  咱們作Android應用的時候,進程須要在一個子線程執行一些耗時的操做,例以下載、播放等。這種狀況咱們通常使用Handler和線程結合處理,子線程負責處理耗時操做,而後通知Handler處理UI更新。Handler和子線程結合處理適合對精度控制要求比較高或者任務耗時比較長或者比較反覆的狀況。除了Handler和線程結合使用,Android也爲咱們提供了另一種選擇,也就是今天要說的AsyncTask。android

  AsyncTask內部也是使用了Handler和線程的模式,只是Google把它封裝好了。下面咱們看看AsyncTask如何使用。編程

 (PS:新建的QQ羣,有興趣能夠加入一塊兒討論:Android羣:322599434)安全

一、android.os.AsyncTask的定義異步

public abstract class AsyncTask<Params, Progress, Result> 
  • Params:輸入的參數
  • Progress:更新的進度,通常用來更新UI的進度信息
  • Result:是執行後的返回結果

這些參數都是泛型定義,因此咱們能夠定義本身的數據類型做爲參數,另外若是不須要相關傳輸,能夠傳入Void便可。ide

 

二、AsyncTask接口函數

//執行異步任務,啓動異步任務須要執行這個接口
public
final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); }
//在execute()被調用後當即執行,能夠作一些任務初始化
protected
void onPreExecute() { }
//在onPreExecute()執行後執行,執行一些耗時操做,此方法將接收輸入參數和返回計算結果。
//在執行過程當中能夠調用publishProgress()來更新進度信息
protected
abstract Result doInBackground(Params... params);
//在調用publishProgress(Progress... values)時,回調這個方法,用來更新進度信息
protected
void onProgressUpdate(Progress... values)
{
}
//doInBackground執行完後,會回調此方法,用於更新界面信息
protected
void onPostExecute(Result result) { }

  上面是AsyncTask的一些重要接口和方法,能夠看出大部分都是空方法還有就是虛函數。咱們繼承AsyncTask的時候,通常都須要重寫上面的方法,方便咱們執行相應的操做。url

 

三、AsyncTask例子spa

下面是我編寫的一個使用AsyncTask下載圖片的例子,這個例子功能是利用AsyncTask下載一張圖片。線程

    private class DownLoad extends AsyncTask<String, Integer, String> 
    {
        //onPreExecute方法在execute()後執行
        @Override  
        protected void onPreExecute() 
        {  
            Log.i(TAG, "onPreExecute() enter");  
            mShowLogTextView.setText("onPreExecute。。。begin downLoad");  
        }  
          
        //doInBackground方法內部執行後臺任務,不能在裏面更新UI,不然有異常。
        @Override  
        protected String doInBackground(String... params) 
        {  
            Log.i(TAG, "doInBackground(String... params) enter");  
            
            URL imageUrl=null;
            try 
            {
                imageUrl=new URL(params[0]);
            } 
            catch (MalformedURLException e) 
            {
                e.printStackTrace();
                Log.e(TAG, e.getMessage());
            }
            try
            {
                //使用HttpURLConnection打開鏈接
                HttpURLConnection urlConn=(HttpURLConnection)imageUrl.openConnection();
                urlConn.setDoInput(true);
                urlConn.connect();
                //將獲得的數據轉化成InputStream
                InputStream is=urlConn.getInputStream();
                //將InputStream轉換成Bitmap
                mDownLoadBtBitmap=BitmapFactory.decodeStream(is);
                is.close();
                //不能在這裏更新UI,不然有異常****** //mNetImageView.setImageBitmap(bitmap);
            }catch(IOException e)
            {
                Log.e(TAG,e.getMessage());
            }
            
            return "ok";
        }  
          
        //onProgressUpdate方法用於更新進度信息  
        @Override  
        protected void onProgressUpdate(Integer... progresses) 
        {  
            Log.i(TAG, "onProgressUpdate(Integer... progresses) enter");  
 
            mShowLogTextView.setText("onProgressUpdate Downloading...");  
        }  
          
        //onPostExecute用於doInBackground執行完後,更新界面UI。 //result是doInBackground返回的結果
        @Override  
        protected void onPostExecute(String result) 
        {  
            Log.i(TAG, "onPostExecute(Result result) called");  
            mShowLogTextView.setText("Down load finish result="+result);  
              
            mNetImageView.setImageBitmap(mDownLoadBtBitmap);
        }  
          
        //onCancelled方法用於取消Task執行,更新UI
        @Override  
        protected void onCancelled() 
        {  
            Log.i(TAG, "onCancelled() called");  
            mShowLogTextView.setText("onCancelled");  
        }  
    }

  上面是繼承了AsyncTask類,重寫了裏面相關方法的之類,從上面能夠看出AsyncTask主要的操做任務都是放到了doInBackground執行。而後onPostExecute最後更新結果。讓AsyncTask開始執行 的方法很簡單,只要調用execute並傳入相關參數便可。

public void onClick(View v)
{
    if (v==mPlayMusicButton)
    {
        //傳入下載圖片的地址 mythou
        mDownLoad.execute("http://pic.desk.chinaz.com/file/10.11.10/7/jillxs40.jpg");
        //mDownLoad.execute("http://www.baidu.com/img/bdlogo.gif");
    } 
} 

  這裏傳入的參數是做爲doInBackground方法的參數,這裏傳入圖片的URL,而後執行下載圖片操做。下面說說AsyncTask使用的時候須要注意的事情。

  • AsyncTask的實例必須在UI線程中建立,而且在UI線程調用execute(Params... params)開始任務。
  • 不要手動調用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),  onPostExecute(Result result)等AsyncTask的回調函數。
  • 不能在doInBackground(Params... params)中更改UI組件的信息。
  • 一個任務實例只能執行一次,若是執行第二次將會拋出異常。

 下面是這個例子執行效果:

 

 

AsyncTask的Demo代碼下載:點擊這裏 

 

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3191174.html 

相關文章
相關標籤/搜索