Android攻城獅AsyncTask

來源:互聯網
上載者:User

標籤:inpu   無法   串連   擷取資料   close   imageview   自動調用   匯入   undle   

構建AsyncTack子類的參數AsyncTask<Params,Progress,Result>是一個抽象類別,通常用於被繼承,繼承AsyncTask需要指定如下三個泛型參數:params:啟動任務時輸入參數的類型。progress:背景工作執行中,返回進度值的類型。Result:後台執行任務完成後,返回結果的類型。------------------------如何構建AsyncTask子類的回調方法?一個完整的AsyncTask通常需要指定如下幾個方法:1. doInBackground:這是AsyncTask子類所必須要重寫的方法,非同步執行後台線程將要完成的任務。我們所有的耗時操作都將在這個方法中進行操作。2. onPreExecute:執行後台耗時操作之前被調用,通常是使用者完成一些初始化操作。3. onPostExecute:當doInBackground()完成後,系統會自動調用此方法,並將doInBackground()返回的值傳給該方法,也就是展示處理完成的結果。4. onProgressUpdate:在doInBackground()方法中調用publishProgrsss()更新任務的執行進度後,就會觸發該方法(必須先調用publishProgrsss()),就可以知道當前耗時操作的完成進度。----------------------------------額外補充:1. 注意這裡的例子繼承的是 AsyncTask<Void,Void,Void>,需要帶上三個泛型,定義Void泛型要注意V是大寫。。。2. 執行順序:onPrRreExecute() --> doInBackground() --> onProgressUpdate()  --> onPostExecute()。



AsyncTask<String,Void,Bitmap>三個參數分別為:url類型,進度實值型別,傳回值類型。這裡的例子暫時不設定進度值,url設定為String類型,又因為我們載入的是一張Bitmap,所以返回的參數類型設定為 Bitmap。1. doInBackground(String...params)傳進來的是一個可變長數組,也就是說,我們可以傳進不止一個參數(通過execute()傳進來),這些參數依次存在於這個數組中。現在只有一個參數,所以只要寫個params[0]取出對應的URL即可。2. 定義一個Bitmap,也就是我們所要擷取的Bitmap。3. 定義一個訪問網路的URLconnection,也就是一個網路連接對象connection。4. 定義一個InputStream,用於擷取資料的輸入資料流。5. 初始化connection:connection = new URL(url).openConnection();這裡需要自行匯入jar包:import java.net.URL; 另外需要try-catch包圍。6. 擷取輸入資料流:is = connection.getInputStream();7. 對輸入資料流進行封裝:BufferedInputStream bis = new BufferedInputStream(is);8. 通過decodeStream()將輸入資料流解析成 Bitmap:bitmap = BitmapFactory.decodeStream(bis);9. 關閉輸入資料流、返回 bitmap。

 1 public class ImageTest extends Activity { 2     private ImageView imageView; 3     private ProgressBar progressBar; 4     String URL = "http://p4.so.qhimgs1.com/sdr/1228_768_/t01f7ed810efbfe800a.jpg"; 5  6     @Override 7     protected void onCreate(Bundle savedInstanceState) { 8         // TODO Auto-generated method stub 9         super.onCreate(savedInstanceState);10         setContentView(R.layout.image);11         imageView = (ImageView) findViewById(R.id.image);12         progressBar = (ProgressBar) findViewById(R.id.bar);13 14         MyAsynctask1 task = new MyAsynctask1();15         task.execute(URL);16 17     }18 19     // params:啟動任務時輸入參數的類型。20     // progress:背景工作執行中,返回進度值的類型。21     // Result:後台執行任務完成後,返回結果的類型。22     class MyAsynctask1 extends AsyncTask<String, Void, Bitmap> {23         @Override24         // 非同步初始化25         protected void onPreExecute() {26             // TODO Auto-generated method stub27             super.onPreExecute();28             // 顯示進度條29             progressBar.setVisibility(View.VISIBLE);30         }31 32         @Override33         protected void onPostExecute(Bitmap result) {34             // TODO Auto-generated method stub35             super.onPostExecute(result);36             progressBar.setVisibility(View.GONE);37             imageView.setImageBitmap(result);38 39         }40 41         @Override42         protected Bitmap doInBackground(String... params) {43             // TODO Auto-generated method stub44 45             // 從params中取出參數值,傳給url46             String url = params[0];47             // 初始化參數48             Bitmap bitmap = null;49             URLConnection connection;50             InputStream inputStream;51 52             try {53                 connection = new URL(url).openConnection();54                 inputStream = connection.getInputStream();// 擷取輸入資料流55                 BufferedInputStream bis = new BufferedInputStream(inputStream);56                 Thread.sleep(3000);// 睡3秒57                 // 通過decodeStream()解析輸入資料流58                 bitmap = BitmapFactory.decodeStream(bis);59                 inputStream.close();60                 bis.close();61 62             } catch (IOException e) {63                 // TODO Auto-generated catch block64                 e.printStackTrace();65             } catch (InterruptedException e) {66                 // TODO Auto-generated catch block67                 e.printStackTrace();68             }69             return bitmap;70         }71 72     }73 74 }

 




反覆執行上一節課的非同步載入,而且是不等進度條滿就後退再執行,會發現後面執行的進度條遲遲沒有響應,為什麼呢?這並非bug,而是 AsyncTask 所實行的一種機制。AsyncTask的底層是通過線程池去作用的。當一個線程沒有完成的時候,後面的線程就無法開始。我們上一節課用了for()迴圈去執行進度條 的更新操作,必須等到for()迴圈結束後才會執行下一個Task。---------那麼,如何去解決這樣的問題呢?很簡單,令AsyncTask的生命週期和Activity或者Fragment的生命週期保持一致就可以了。回到ProgressBar,重寫onPause(),在Activity執行onPause()的時候,對AsyncTask進行判斷:如果AsyncTask不為空白且處於Running狀態,我們就要取消該線程:    protected void onPause() {        super.onPause();        if(mTask!=null && mTask.getStatus()==AsyncTask.Status.RUNNING){            mTask.cancel(true);        }    }cancle()方法只是將對應的AsyncTask標記為cancel狀態,並不是真正地取消線程的執行。另外,我們在Java中也是沒辦法直接粗暴地停止一個線程,我們必須要等一個線程執行完畢之後才能繼續其他線程的操作。--------------那要如何快速停止線程呢?1. 在onPause()中標記取消狀態:mTask.cancel(true);既然我們已經標記了cancel狀態,那麼可以在AsyncTask中監測這樣的改變,一旦目前狀態改為cancelled,我們就要跳出迴圈,立刻結束當前操作,從而結束整個線程邏輯。2. 在doInBackground()方法的for()迴圈內添加isCancelled()對線程的狀態進行判斷:if(isCancelled())break;3. 同理,在onProgressUpdate()方法中也做類似的處理:if(isCancelled())return;通過如上操作,我們就能快速停止當前線程,將處理權交給下一個AsyncTask。
 1 public class ProgressBarTest extends Activity { 2  3     ProgressBar progressBar; 4     MyAsycnTask2 task; 5     @Override 6     protected void onCreate(Bundle savedInstanceState) { 7         // TODO Auto-generated method stub 8         super.onCreate(savedInstanceState); 9         setContentView(R.layout.progressbar);10         progressBar = (ProgressBar) findViewById(R.id.progressBar1);11 12          task = new MyAsycnTask2();13         task.execute();14     }15 16     @Override17     protected void onPause() {18         // TODO Auto-generated method stub19         super.onPause();20         if (task!=null&&task.getStatus()==AsyncTask.Status.RUNNING) {21             task.cancel(true);//cancel()只是將對應的task標記為cancel狀態,並不是真正取消線程執行22         }23     }24 25     class MyAsycnTask2 extends AsyncTask<Void, Integer, Void> {26 27         @Override28         protected void onProgressUpdate(Integer... values) {29             // TODO Auto-generated method stub30             // 擷取進度更新值31             super.onProgressUpdate(values);32             if (isCancelled()) {33                 return;34             }35             progressBar.setProgress(values[0]);36         }37 38         @Override39         protected Void doInBackground(Void... params) {40             // TODO Auto-generated method stub41             42             // 類比進度更新43             for (int i = 0; i < 100; i++) {44                 if (isCancelled()) {45                 break;46             }47                 publishProgress(i);48                 try {49                     Thread.sleep(300);50                 } catch (InterruptedException e) {51                     // TODO Auto-generated catch block52                     e.printStackTrace();53                 }54             }55             return null;56         }57     }58 }

 



Android攻城獅AsyncTask

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.