Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> Android AsyncTask分析

Android AsyncTask分析

編輯:Android編程入門

---恢復內容開始---

因為android的UI線程是不安全的,如果你UI線程裡執行一些耗時任務,很容易就導致程序崩潰。並且目前網絡任務也不能夠在UI線程裡執行。處理這些問題除了直接寫一個線程以外,Android還提供一個AsyncTask(異步任務類)來更簡單的處理一些耗時任務。

 

AsyncTask<>是一個抽象類,通常用於繼承,繼承時需要指定三個泛型參數。

1、Params:啟動任務時傳入的參數的類型。這是一個數組,可以傳多個參數。調用時使用params[0]、params[1]、params[2]來獲取。

2、Progress:後台任務完成的進度值的類型。

3、Result:後台任務執行完畢返回結果的類型。

 

使用AsyncTask需要如下三步:

1、繼承抽象類,實現一個子類,傳入三個泛型參數。如果有參數不需要使用可設為Void。

2、根據需要,可實現以下方法。

  • doInBackground(Params...):該方法是必須的,這個方法下寫的是後台線程要執行的任務,並且會在子線程運行(其他方法都是在UI線程執行)。。該方法可以調用publicProgress(Progress...values)方法更新任務的進度。
  • onProgressUpdate(Progress... values):該方法在上一步調用publicProgress時觸發。
  • onPreExecute():該方法會在執行doInBackground方法前執行,用於做一些准備工作。
  • onPostExecute(Result result):當doInBackground執行結束之後,系統會自動調用該方法,返回值也會傳到此函數。我們可以在這裡完成後台線程執行後的結果。

3、最後用新建我們繼承類後的結果,然後調用execute(Params... params)。

  注意:對象必須在UI線程中創建、execute方法必須在UI線程中調用、以上四個方法都需系統自動調用、每個對象只能被執行一次,多次調用引發異常。

 

實例

講了那麼多鋪墊,讓我們來講個例子吧~

我現在想從互聯網上下載一張圖片,就使用這個AsyncTask來做一下吧~

 為讓所有方法都實現一次,我們用兩種方法實現:1、下載完畢後直接進行顯示。2、一邊加載一邊顯示進度,加載完畢顯示圖片。

下面是第一種的代碼,相對簡單一點,只用了兩個函數。

public class MainActivity extends Activity {
    
    int downloadSize;
    int fileSize;
    
    Button bn;
    ImageView iv;
    ProgressBar progressBar;
    String url = "/hvtimg/bjafjc/3xglb9xf.jpg";
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        bn = (Button) findViewById(R.id.down);
        iv = (ImageView) findViewById(R.id.image);
        
        MyOnClickListener myOnClickListener = new MyOnClickListener();
        bn.setOnClickListener(myOnClickListener);
    }
    
    class MyOnClickListener implements android.view.View.OnClickListener{
        
        @Override
        public void onClick(View v) {
            
            AsyncDownload asyncDownload = new AsyncDownload();
            asyncDownload.execute(url);
        }        
    }
    
    class AsyncDownload extends AsyncTask<String, Integer, Bitmap>
    {
        
        @Override
        protected Bitmap doInBackground(String... params) {

            String imageUrl = params[0];
            
            URL url;
            try {
                url = new URL(imageUrl);
                InputStream is = url.openStream();
                BitmapFactory.Options op = new BitmapFactory.Options();
                op.inSampleSize = 2;
                Bitmap bitmap = BitmapFactory.decodeStream(is, null,
                        op);
                
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
        
        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);
            
            iv.setImageBitmap(result);
        }
  }
}

上面的代碼的功能是點擊按鈕,然後doInBackground後台下載圖片,下載完畢onPostExecute顯示圖片。僅僅使用了兩個函數,但是實現了AsyncTask的核心功能。

 

然後讓我們感受一下能夠顯示進度的。

public class MainActivity extends Activity {
    
    int downloadSize;
    int fileSize;
    
    Button bn;
    ImageView iv;
    ProgressBar progressBar;
    String url = "/hvtimg/bjafjc/3xglb9xf.jpg";
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        bn = (Button) findViewById(R.id.down);
        iv = (ImageView) findViewById(R.id.image);
        progressBar = (ProgressBar) findViewById(R.id.bar);
        
        MyOnClickListener myOnClickListener = new MyOnClickListener();
        bn.setOnClickListener(myOnClickListener);
    }
    
    Handler handler = new Handler(){
        
        public void handleMessage(android.os.Message msg) 
        {
            
        }
    };
    
    class MyOnClickListener implements android.view.View.OnClickListener{
        
        @Override
        public void onClick(View v) {
            
            AsyncDownload asyncDownload = new AsyncDownload();
            asyncDownload.execute(url);
        }        
    }
    
    class AsyncDownload extends AsyncTask<String, Integer, Void>
    {
        
        @Override
        protected Void doInBackground(String... params) {

            String imageUrl = params[0];
            
            try {
                URL url = new URL(imageUrl);
                URLConnection conn = url.openConnection(); 
                conn.connect(); 
                InputStream is = conn.getInputStream(); 
                fileSize = conn.getContentLength(); 
                
                publishProgress(0x111);
                
                FileOutputStream fos = new FileOutputStream(getPath());
                byte[] bytes = new byte[1024]; 
                int len = -1; 
                while((len = is.read(bytes))!=-1) 
                { 
                    fos.write(bytes, 0, len); 
                    downloadSize+=len; 
                    publishProgress(0x222);
                } 
                publishProgress(0x333);
                is.close(); 
                fos.close(); 
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null; 
        }
        
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            
            switch(values[0])
            {
            case 0x111:
                progressBar.setMax(fileSize);
                break;
            case 0x222:
                progressBar.setProgress(downloadSize);
                break;
            case 0x333:
                try { 
                    if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){ 
                        FileInputStream fis = new FileInputStream(getPath()); 
                        iv.setImageBitmap(BitmapFactory.decodeStream(fis)); 
                    } 
                    downloadSize = 0; 
                    fileSize = 0; 
                } catch (FileNotFoundException e) { 
                    e.printStackTrace(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
                break;
            }
        }
    }
    
    public String getPath() {
        File root = getExternalCacheDir();
        if (root != null)
        {
            return root.getAbsolutePath()  + "test.jpg";
        }
        
        return null;
    }
}

這裡實現的功能是點擊下載按鈕,後台從互聯網加載文件,首先獲取文件大小,設置progressbar最大值,然後一邊下載、一邊存入本地、一邊設置progressbar的值,實現進度條。下載完畢從本地獲取圖片顯示出來。這一次多使用了顯示進度的函數onProgressUpdate。

 

其實,onProgressUpdate這個函數一般我們在線程裡會用Handler來實現。

在AsyncTask給我們把平常使用線程進行異步操作的所用東西打包在一起了,不得不說確實省了一些事。

實際上能夠用AsyncTask實現的東西完全可以直接用線程來實現~

 

我在些第二個代碼的時候寫順了手,用Handler實現了一遍,大家在下面可以看一下。

public class MainActivity extends Activity {
    
    int downloadSize;
    int fileSize;
    
    Button bn;
    ImageView iv;
    ProgressBar progressBar;
    String url = "/hvtimg/bjafjc/3xglb9xf.jpg";
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        bn = (Button) findViewById(R.id.down);
        iv = (ImageView) findViewById(R.id.image);
        progressBar = (ProgressBar) findViewById(R.id.bar);
        
        MyOnClickListener myOnClickListener = new MyOnClickListener();
        bn.setOnClickListener(myOnClickListener);
    }
    
    Handler handler = new Handler(){
        
        public void handleMessage(android.os.Message msg) 
        {
            switch(msg.what)
            {
            case 0x111:
                progressBar.setMax(fileSize);
                break;
            case 0x222:
                progressBar.setProgress(downloadSize);
                break;
            case 0x333:
                try { 
                    if(getPath().endsWith(".jpg")||getPath().endsWith(".png")){ 
                        FileInputStream fis = new FileInputStream(getPath()); 
                        iv.setImageBitmap(BitmapFactory.decodeStream(fis)); 
                    } 
                    downloadSize = 0; 
                    fileSize = 0; 
                } catch (FileNotFoundException e) { 
                    e.printStackTrace(); 
                } catch (IOException e) { 
                    e.printStackTrace(); 
                } 
                break;
            }
        }
    };
    
    class MyOnClickListener implements android.view.View.OnClickListener{
        
        @Override
        public void onClick(View v) {
            
            AsyncDownload asyncDownload = new AsyncDownload();
            asyncDownload.execute(url);
        }        
    }
    
    class AsyncDownload extends AsyncTask<String, Integer, Void>
    {
        
        @Override
        protected Void doInBackground(String... params) {

            String imageUrl = params[0];
            
            try {
                URL url = new URL(imageUrl);
                URLConnection conn = url.openConnection(); 
                conn.connect(); 
                InputStream is = conn.getInputStream(); 
                fileSize = conn.getContentLength(); 
                
                handler.sendEmptyMessage(0x111);
                
                FileOutputStream fos = new FileOutputStream(getPath());
                byte[] bytes = new byte[1024]; 
                int len = -1; 
                while((len = is.read(bytes))!=-1) 
                { 
                    fos.write(bytes, 0, len); 
                    downloadSize+=len; 
                    handler.sendEmptyMessage(0x222);
                } 
                handler.sendEmptyMessage(0x333);
                is.close(); 
                fos.close(); 
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null; 
        }
    }
    
    public String getPath() {
        File root = getExternalCacheDir();
        if (root != null)
        {
            return root.getAbsolutePath()  + "test.jpg";
        }
        
        return null;
    }
}

 

啦啦啦,就到這裡吧~

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved