Android攻城狮AsyncTask
生活随笔
收集整理的這篇文章主要介紹了
Android攻城狮AsyncTask
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
構建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。
?
反復執行上一節課的異步加載,而且是不等進度條滿就后退再執行,會發現后面執行的進度條遲遲沒有響應,為什么呢?這并非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 @Override 17 protected void onPause() { 18 // TODO Auto-generated method stub 19 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 @Override 28 protected void onProgressUpdate(Integer... values) { 29 // TODO Auto-generated method stub 30 // 獲取進度更新值 31 super.onProgressUpdate(values); 32 if (isCancelled()) { 33 return; 34 } 35 progressBar.setProgress(values[0]); 36 } 37 38 @Override 39 protected Void doInBackground(Void... params) { 40 // TODO Auto-generated method stub 41 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 block 52 e.printStackTrace(); 53 } 54 } 55 return null; 56 } 57 } 58 }
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 //Asynctask加載網絡圖片 2 //使用ProgressBar 和ProgressDialog提示下載的進度 3 4 public class ImageTest extends Activity { 5 private ImageView imageView; 6 private ProgressBar progressBar;// 方式一:對話框提示進度 7 String URL = "http://p4.so.qhimgs1.com/sdr/1228_768_/t01f7ed810efbfe800a.jpg"; 8 ProgressDialog dialog;// 方式二:對話框提示進度 9 MyAsynctask1 task; 10 11 @Override 12 protected void onCreate(Bundle savedInstanceState) { 13 // TODO Auto-generated method stub 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.image); 16 imageView = (ImageView) findViewById(R.id.image); 17 progressBar = (ProgressBar) findViewById(R.id.bar); 18 19 dialog = new ProgressDialog(this); 20 dialog.setTitle("提示信息:"); 21 dialog.setMessage("laoding...."); 22 dialog.setProgressStyle(dialog.STYLE_HORIZONTAL); 23 24 MyAsynctask1 task = new MyAsynctask1(); 25 task.execute(URL); 26 27 } 28 29 // 不等進度條滿就后退再執行,會發現后面執行的進度條遲遲沒有響應, 30 // 令AsyncTask的生命周期和Activity或者Fragment的生命周期保持一致就可以了。 31 @Override 32 protected void onPause() { 33 // TODO Auto-generated method stub 34 super.onPause(); 35 if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) { 36 task.cancel(true); 37 // cancel()只是將對應的task標記為cancel狀態,并不是真正取消線程執行 38 } 39 } 40 41 // params:啟動任務時輸入參數的類型。 42 // progress:后臺任務執行中,返回進度值的類型。 43 // Result:后臺執行任務完成后,返回結果的類型。 44 45 // 2. 執行順序:onPrRreExecute() --> doInBackground() --> onProgressUpdate() --> 46 // onPostExecute()。 47 class MyAsynctask1 extends AsyncTask<String, Integer, Bitmap> { 48 @Override 49 // 1.執行后臺耗時操作之前被調用,通常是用戶完成一些初始化操作。 50 protected void onPreExecute() { 51 // TODO Auto-generated method stub 52 super.onPreExecute(); 53 // 顯示進度條 54 progressBar.setVisibility(View.VISIBLE); 55 dialog.show(); 56 } 57 58 // 4.當doInBackground()完成后,系統會自動調用此方法,并將doInBackground()返回的值傳給該方法,也就是展示處理完成的結果。 59 @Override 60 protected void onPostExecute(Bitmap result) { 61 // TODO Auto-generated method stub/ 62 super.onPostExecute(result); 63 progressBar.setVisibility(View.GONE);// 消失進度條 64 dialog.dismiss(); 65 imageView.setImageBitmap(result); 66 67 } 68 69 // 2. 70 // doInBackground:這是AsyncTask子類所必須要重寫的方法,異步執行后臺線程將要完成的任務。我們所有的耗時操作都將在這個方法中進行操作。 71 @Override 72 protected Bitmap doInBackground(String... params) { 73 // TODO Auto-generated method stub 74 75 // 從params中取出參數值,傳給url 76 String url = params[0]; 77 // 初始化參數 78 Bitmap bitmap = null; 79 URLConnection connection; 80 InputStream inputStream; 81 82 try { 83 connection = new URL(url).openConnection(); 84 inputStream = connection.getInputStream();// 獲取輸入流 85 BufferedInputStream bis = new BufferedInputStream(inputStream); 86 Thread.sleep(5000);// 睡3秒 87 // 通過decodeStream()解析輸入流 88 bitmap = BitmapFactory.decodeStream(bis); 89 inputStream.close(); 90 bis.close(); 91 92 } catch (IOException e) { 93 // TODO Auto-generated catch block 94 e.printStackTrace(); 95 } catch (InterruptedException e) { 96 // TODO Auto-generated catch block 97 e.printStackTrace(); 98 } 99 // 模擬進度更新 100 for (int i = 0; i < 100; i++) { 101 if (isCancelled()) { 102 break; 103 } 104 publishProgress(i); 105 106 } 107 return bitmap; 108 } 109 110 // 3.在doInBackground()方法中調用publishProgrsss()更新任務的執行進度后,就會觸發該方法(必須先調用publishProgrsss()),就可以知道當前耗時操作的完成進度。 111 @Override 112 protected void onProgressUpdate(Integer... values) { 113 // TODO Auto-generated method stub 114 super.onProgressUpdate(values); 115 if (isCancelled()) { 116 return; 117 118 } 119 dialog.setProgress(values[0]); 120 progressBar.setProgress(values[0]); 121 } 122 123 } 124 125 }?
反復執行上一節課的異步加載,而且是不等進度條滿就后退再執行,會發現后面執行的進度條遲遲沒有響應,為什么呢?這并非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 @Override 17 protected void onPause() { 18 // TODO Auto-generated method stub 19 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 @Override 28 protected void onProgressUpdate(Integer... values) { 29 // TODO Auto-generated method stub 30 // 獲取進度更新值 31 super.onProgressUpdate(values); 32 if (isCancelled()) { 33 return; 34 } 35 progressBar.setProgress(values[0]); 36 } 37 38 @Override 39 protected Void doInBackground(Void... params) { 40 // TODO Auto-generated method stub 41 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 block 52 e.printStackTrace(); 53 } 54 } 55 return null; 56 } 57 } 58 }
?
轉載于:https://www.cnblogs.com/my334420/p/6724539.html
總結
以上是生活随笔為你收集整理的Android攻城狮AsyncTask的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python批量请求url_python
- 下一篇: android sina oauth2.