android 使用AsyncTask實現非同步下載檔案
阿新 • • 發佈:2019-01-13
android中的非同步方法也很多,之前一直使用Handler+Thread的方法,今天學習了AsyncTask,來實現耗時操作:從網路下載檔案。
AsyncTask定義了三種泛型型別Params,Progress和Result。
我們使用AsyncTask實現4個常用的方法來完成相應的功能,如下:
(1) doInBackground: 子執行緒中執行,耗時操作。將執行結束的結果返回onPostExecute()引數中
(2) onPreExecute: 執行在UI執行緒中,任務執行前的準備
(3) onPostExecute: 執行在UI執行緒中,處理非同步執行緒的任務結果
(4) onProgressUpdate: 執行在UI執行緒中,更新當前進度條資訊,被publishProgress回撥
DownFileActivity :
public class DownFileActivity extends Activity implements View.OnClickListener { /* SD卡根目錄 */ private File rootDie; /* 輸出檔名稱 */ private String outFileName = "ldjfh.jar"; /* 進度條對話方塊 */ private ProgressDialog pdialog; private MyLoadAsyncTask myLoadAsyncTask = new MyLoadAsyncTask(); @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.downfile); checkAndCreateDir(); getPermission();//動態獲取許可權 findViewById(R.id.file_download_btn).setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == R.id.file_download_btn) { /* 非同步下載 */ myLoadAsyncTask.execute("http://192.168");//有效的URL地址 } } //AsyncTask是基於執行緒池進行實現的,當一個執行緒沒有結束時,後面的執行緒是不能執行的. @Override protected void onDestroy() { super.onDestroy(); if (myLoadAsyncTask != null && myLoadAsyncTask.getStatus() == AsyncTask.Status.RUNNING) { //cancel方法只是將對應的AsyncTask標記為cancelt狀態,並不是真正的取消執行緒的執行. myLoadAsyncTask.cancel(true); } } @Override protected Dialog onCreateDialog(int id) { /* 例項化進度條對話方塊 */ pdialog = new ProgressDialog(this); /* 進度條對話方塊屬性設定 */ pdialog.setMessage("正在下載中..."); /* 進度值最大100 */ pdialog.setMax(100); /* 水平風格進度條 */ pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); /* 無限迴圈模式 */ pdialog.setIndeterminate(false); /* 可取消 */ pdialog.setCancelable(true); /* 顯示對話方塊 */ pdialog.show(); return pdialog; } /* 檢查sdcard並建立目錄檔案 */ private void checkAndCreateDir() { /* 獲取sdcard目錄 */ rootDie = Environment.getExternalStorageDirectory(); /* 新檔案的目錄 */ File newFile = new File(rootDie + "/download1/"); if (!newFile.exists()) { /* 如果檔案不存在就建立目錄 */ newFile.mkdirs(); } } /** * 動態獲取許可權 */ private void getPermission() { PackageManager pm = getPackageManager(); boolean permission = (PackageManager.PERMISSION_GRANTED == pm.checkPermission("android.permission.WRITE_EXTERNAL_STORAGE", "com.zhengyuan.learningserverdownloadfile")); if (permission) { Toast.makeText(DownFileActivity.this, "有許可權", Toast.LENGTH_SHORT).show(); } else { //版本高於6.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.INTERNET}, 12); } } //申請許可權 } /* 非同步任務,後臺處理與更新UI */ class MyLoadAsyncTask extends AsyncTask<String, String, String> { /* 後臺執行緒 */ @Override protected String doInBackground(String... params) { /* 所下載檔案的URL */ try { URL url = new URL(params[0]); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); /* URL屬性設定 */ conn.setRequestMethod("GET"); /* URL建立連線 */ conn.connect(); /* 下載檔案的大小 */ int fileOfLength = conn.getContentLength(); /* 每次下載的大小與總下載的大小 */ int totallength = 0; int length = 0; /* 輸入流 */ InputStream in = conn.getInputStream(); /* 輸出流 */ FileOutputStream out = new FileOutputStream(new File(rootDie + "/download1/", outFileName)); /* 快取模式,下載檔案 */ byte[] buff = new byte[1024 * 1024]; while ((length = in.read(buff)) > 0) { totallength += length; String str1 = "" + (int) ((totallength * 100) / fileOfLength); publishProgress(str1); out.write(buff, 0, length); } /* 關閉輸入輸出流 */ in.close(); out.flush(); out.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /* 預處理UI執行緒 */ @Override protected void onPreExecute() { showDialog(0); super.onPreExecute(); } /* 結束時的UI執行緒 */ @Override protected void onPostExecute(String result) { dismissDialog(0); super.onPostExecute(result); } /* 處理UI執行緒,會被多次呼叫,觸發事件為publicProgress方法 */ @Override protected void onProgressUpdate(String... values) { /* 進度顯示 */ pdialog.setProgress(Integer.parseInt(values[0])); } } }
downfile.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/file_download_btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="下載檔案" android:textSize="16sp" /> </LinearLayout>
有時候我們需要activity結束後,下載也結束,但是因為是後臺執行,即時activity結束後,檔案還是會被下載下來。
我們在onDestroy新增如下程式碼
@Override
protected void onDestroy() {
super.onDestroy();
if (myLoadAsyncTask != null && myLoadAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
//cancel方法只是將對應的AsyncTask標記為cancelt狀態,並不是真正的取消執行緒的執行.
myLoadAsyncTask.cancel(true);
}
}
當然AsyncTask還有跟多的功能需要學習,在網上找到一個比較好的部落格。