AsyncTask異步實現文件下載

cmn6 9年前發布 | 5K 次閱讀 Java Android

   做android開發的都知道,我們在主線程中不能進行耗時太久的操作,否則就可能報ANR,所有耗時的操作都要異步進行。android中的異步方法 也很多,可以用Handler,可以用Thread及Runnable等。今天我們用安卓自帶的異步工具AsyncTask來實現耗時操作:從網絡下載文 件。先對AsyncTask作個簡單的介紹,下面的介紹也主要是參考網上資料: 

1,AsyncTask定義了三種泛型類型 Params,Progress和Result。

  • Params 啟動任務執行的輸入參數,如網絡請求的URL。
  • Progress 后臺進行中任務執行進度百分比。
  • Result 后臺執行任務完成最終返回的結果,比如String,Bitmap等。

2,使用AsyncTask 最少要重寫以下這兩個方法:

  • doInBackground(Params…) 后臺執行,耗時的操作都可以放在這里(這里不能直接操作UI)。在執行過程中可以調用publicProgress(Progress…)來更新任務的進度,并用進度條顯示出來。
  • onPostExecute(Result)  相當于Handler 處理UI的方式,在這里面可以使用在doInBackground 得到的結果處理操作UI。 此方法在主線程執行,任務執行的結果作為此方法的參數返回。

3,有進我還需要重寫以下這三個方法(非必需):

  • onProgressUpdate(Progress…)   可以使用進度條增加用戶體驗度。 此方法在主線程執行,用于顯示任務執行的進度。
  • onPreExecute() 當任務執行之前開始調用此方法,可以在這里顯示進度對話框。
  • onCancelled()   用戶調用取消時,要做的操作可以放到這里面處理。

4,使用AsyncTask類,以下是幾條必須遵守的準則:

  • AsyncTask的實例和execute方法必須在UI線程中創建,
  • 不要手動調用onPreExecute(), onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)這4個方法,
  • 該實現的AsyncTask只能被執行一次,否則多次調用時將會出現異常;                                                             下面是我們實現文件下載的例子:
  • 布局:
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        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:textSize="16sp"
            android:text="下載文件" />
    
    
    </LinearLayout>
  • Activity代碼:
    public class MainActivity extends Activity implements OnClickListener {
    /* SD卡根目錄 */
    private File rootDie;
    /* 輸出文件名稱 */
    private String outFileName = "ldm.rar";
    /* 進度條對話框 */
    private ProgressDialog pdialog;
    
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    checkAndCreateDir();
    findViewById(R.id.file_download_btn).setOnClickListener(this);
    }
    
    
    @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 + "/download/");
    if (!newFile.exists()) {
    /* 如果文件不存在就創建目錄 */
    newFile.mkdirs();
    }
    }
    
    
    /* 異步任務,后臺處理與更新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 + "/mydownload1/", 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]));
    }
    
    
    }
    
    
    @Override
    public void onClick(View v) {
    if (v.getId() == R.id.file_download_btn) {
    /* 異步下載 */
    new MyLoadAsyncTask().execute("http://192.168.1.105:8080/tool.rar");
    }
    }
    
    }

  • 最后別忘記在AndroidManifest.xml中加上權限:
    <!-- sdcard讀寫權限 -->
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <!-- sdcard創建目錄與文件權限 -->
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <!-- 網絡訪問權限 -->
        <uses-permission android:name="android.permission.INTERNET" />

 本文由用戶 cmn6 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!