標籤:str max img ima 即時 asynctask 執行個體 android async
Android提供了一個工具類:AsyncTask,它使建立需要與使用者介面互動的長時間啟動並執行任務變得更簡單。相對Handler來說AsyncTask更輕量級一些,適用於簡單的非同步處理,不需要藉助線程和Handter即可實現。AsyncTask是抽象類別。AsyncTask定義了三種泛型型別Params,Progress和Result:
Params啟動任務執行的輸入參數,比如,HTTP請求的URL。
Progress背景工作執行的百分比。
Result後台執行任務最終返回的結果,比如String。
通過用AsyncTask實現檔案下載以及進度更新提示的示範動圖:
本次真機示範的下載目錄為Download檔案夾,首先進入Download檔案夾,沒有圖片檔案,下載完成後,再次查看,可以看到本次示範的下載圖片
首先我們簡單介紹AsyncTask的執行步驟:
AsyncTask的執行分為四個步驟,每一步對應一個回調方法,我們需要的就是實現這些方法。
(1)首先定義一個類繼承AsyncTask
(2)實現AsyncTask中定義的下面一個或幾個方法
四個步驟方法分別為:
(1)onPreExecute():被UIThread調用,該方法用來做一些準備工作,如在介面上顯示一個進度條。
(2)dolnBackground(Params…):將在onPreExecute之後執行,運行在後台線程中。負責執行耗時工作。可以調用publishProgress方法來更新即時任務進度。
(3)onProgressUpdate(Progress…):在publishProgress方法被調用後,UIThread將調用該方法在介面上展示任務的進展情況,例如通過一個進度條進行展示。
(4)onPostExecute(Result):在dolnBackground執行完成後,onPostExecute方法將被UIThread調用,背景計算結果將通過該方法傳遞到UIThread。
效果實現程式碼範例:
第一步:Layout中Activity的布局檔案activity_main.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:id="@+id/activity_main" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 android:orientation="vertical" 9 tools:context="com.example.administrator.asynctask.MainActivity">10 <TextView11 android:id="@+id/tv"12 android:layout_width="match_parent"13 android:layout_height="wrap_content"14 android:text="panhouye!"15 android:textSize="20sp"/>16 <ProgressBar17 android:id="@+id/progress"18 android:layout_width="match_parent"19 android:layout_height="wrap_content"20 style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"21 android:visibility="visible"/>22 <Button23 android:layout_width="match_parent"24 android:layout_height="wrap_content"25 android:onClick="image"26 android:text="下載圖片"/>27 </LinearLayout>
第二步:Java實現代碼MainActivity.java檔案
1 import android.os.AsyncTask; 2 import android.os.Environment; 3 import android.support.v7.app.AppCompatActivity; 4 import android.os.Bundle; 5 import android.view.View; 6 import android.widget.ProgressBar; 7 import android.widget.TextView; 8 import java.io.BufferedInputStream; 9 import java.io.BufferedOutputStream;10 import java.io.File;11 import java.io.FileOutputStream;12 import java.net.HttpURLConnection;13 import java.net.URL;14 /**15 * Created by panchengjia on 2016/12/19.16 */17 public class MainActivity extends AppCompatActivity {18 //聲明publishProgress的更新標記19 private static final int PROGRESS_MAX = 0X1;20 private static final int UPDATE = 0X2;21 private TextView tv;22 ProgressBar progress;23 int contentLen;//聲明要下載的檔案總長24 @Override25 protected void onCreate(Bundle savedInstanceState) {26 super.onCreate(savedInstanceState);27 setContentView(R.layout.activity_main);28 tv = (TextView) findViewById(R.id.tv);29 progress = (ProgressBar) findViewById(R.id.progress);30 }31 public void image(View view){32 //啟用AsyncTask,傳入需要執行的內容(圖片地址)33 new DownLoad().execute("http://cdnq.duitang.com/uploads/item/201402/22/20140222115440_jWNmx.thumb.700_0.jpeg");34 }35 class DownLoad extends AsyncTask<String,Integer,String>{36 //在執行實際的後台操作前被UI Thread調用37 @Override38 protected void onPreExecute() {39 super.onPreExecute();40 //準備下載前的初始進度41 progress.setProgress(0);42 }43 //在onPreExecute執行,該方法運行在後台線程中44 @Override45 protected String doInBackground(String... params) {46 try {47 URL url = new URL(params[0]);48 //擷取串連49 HttpURLConnection connection = (HttpURLConnection) url.openConnection();50 //擷取下載檔案的大小51 contentLen = connection.getContentLength();52 //根據下載檔案大小設定進度條最大值(使用標記區別即時進度更新)53 publishProgress(PROGRESS_MAX,contentLen);54 //迴圈下載(邊讀取邊存入)55 BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());56 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new57 File(Environment.getExternalStorageDirectory()+"/Download/ss.jpg")));58 int len =-1;59 byte[] bytes = new byte[1024];60 while((len=bis.read(bytes))!=-1){61 bos.write(bytes,0,len);62 bos.flush();63 //即時更新下載進度(使用標記區別最大值)64 publishProgress(UPDATE,len);65 //示範下載的圖片太小,網速太快,休眠300毫秒,方便大家觀察66 Thread.sleep(300);67 }68 bos.close();69 bis.close();70 } catch (Exception e) {71 e.printStackTrace();72 }73 return "下載完成";74 }75 //在publishProgress被調用後,UI thread會調用這個方法76 @Override77 protected void onProgressUpdate(Integer... values) {78 super.onProgressUpdate(values);79 switch (values[0]){80 case PROGRESS_MAX:81 progress.setMax(values[1]);82 break;83 case UPDATE:84 progress.incrementProgressBy(values[1]);85 //擷取下載進度百分比並更新textview86 int i=(progress.getProgress()*100)/contentLen;87 tv.setText("下載進度為:"+i+"%");88 break;89 }90 }91 //doInBackground方法執行完後被UI thread執行92 @Override93 protected void onPostExecute(String s) {94 super.onPostExecute(s);95 progress.setVisibility(View.GONE);96 tv.setText(s);97 }98 }99 }最後強調一下AsyncTask的設計準則:
(1)AsyncTask的執行個體必須在UlThread中建立。
(2)execute方法必須在UlThread中調用。
(3)不要手動的調用onPreExecute(),onPostExecute(Result),dolnBackground(Params…),onProgressUpdate(Progress…)這幾個方法。
(4)該Task只能被執行一次,否則多次調用時將會出現異常。
(5)AsyncTask不能完全取代線程,在一些邏輯較為複雜或者需要在後台反覆執行的邏輯就可能需要線程來實現了。
Android中使用AsyncTask實現檔案下載以及進度更新提示