AsyncTask用法解析-下载文件动态更新进度条

1. 泛型

AysncTask<Params, Progress, Result>

Params:启动任务时传入的参数,通过调用asyncTask.execute(param)方法传入。

Progress:后台任务执行的进度,若不用显示进度条,则不需要指定。

Result:后台任务结束时返回的结果。

2. 重要方法

doInBackground(Params... params):必须重写的方法,后台任务就在这里执行,会开启一个新的线程。params为启动任务时传入的参数,参数个数不定。

onPreExecute():在主线程中调用,在后台任务开启前的操作在这里进行,例如显示一个进度条对话框。

onPostExecute(Result result):当后台任务结束后,在主线程中调用,处理doInBackground()方法返回的结果。

onProgressUpdate(Progress... values):当在doInBackground()中调用publishProgress(Progress... values)时,返回主线程中调用,这里的参数个数也是不定的。

onCancelled():取消任务。

重要方法执行过程

3. 注意事项

(1)execute()方法必须在主线程中调用;

(2)AsyncTask实例必须在主线程中创建;

(3)不要手动调用doInBackground()、onPreExecute()、onPostExecute()、onProgressUpdate()方法;

(4)注意防止内存泄漏,在doInBackground()方法中若出现对Activity的强引用,可能会造成内存泄漏。

4. 下载文件动态更新进度条(未封装)

布局:

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:padding="20dp"
    tools:context="com.studying.asynctaskdemo.MainActivity">

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:progress="0" />

    <Button
        android:id="@+id/download"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="20dp"
        android:text="@string/start_btn" />

    <TextView
        android:id="@+id/status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="@string/waiting" />

</LinearLayout>

Activity:

public class MainActivity extends Activity {

    private static final String FILE_NAME = "test.pdf";//下载文件的名称
    private static final String PDF_URL = "http://clfile.imooc.com/class/assist/118/1328281/AsyncTask.pdf";

    private ProgressBar mProgressBar;
    private Button mDownloadBtn;
    private TextView mStatus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initView();
        setListener();
    }

    private void initView() {
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mDownloadBtn = (Button) findViewById(R.id.download);
        mStatus = (TextView) findViewById(R.id.status);
    }

    private void setListener() {
        mDownloadBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //AsyncTask实例必须在主线程创建
                DownloadAsyncTask asyncTask = new DownloadAsyncTask();
                asyncTask.execute(PDF_URL);
            }
        });
    }

    /**
     * 泛型:
     * String:传入参数为文件下载地址
     * Integer:下载过程中更新ProgressBar的进度
     * Boolean:是否下载成功
     */
    private class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {

        private String mFilePath;//下载文件的保存路径

        @Override
        protected Boolean doInBackground(String... params) {
            if (params != null && params.length > 0) {
                String pdfUrl = params[0];

                try {
                    URL url = new URL(pdfUrl);
                    URLConnection urlConnection = url.openConnection();
                    InputStream in = urlConnection.getInputStream();
                    int contentLength = urlConnection.getContentLength();//获取内容总长度

                    mFilePath = Environment.getExternalStorageDirectory() + File.separator + FILE_NAME;

                    //若存在同名文件则删除
                    File pdfFile = new File(mFilePath);
                    if (pdfFile.exists()) {
                        boolean result = pdfFile.delete();
                        if (!result) {
                            return false;
                        }
                    }

                    int downloadSize = 0;//已经下载的大小
                    byte[] bytes = new byte[1024];
                    int length = 0;
                    OutputStream out = new FileOutputStream(mFilePath);
                    while ((length = in.read(bytes)) != -1) {
                        out.write(bytes, 0, length);
                        downloadSize += length;
                        publishProgress(downloadSize / contentLength * 100);
                    }

                    in.close();
                    out.close();

                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
            } else {
                return false;
            }
            return true;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mDownloadBtn.setText("下载中");
            mDownloadBtn.setEnabled(false);
            mStatus.setText("下载中");
            mProgressBar.setProgress(0);
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            mDownloadBtn.setText("下载完成");
            mStatus.setText(aBoolean ? "下载完成" + mFilePath : "下载失败");
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (values != null && values.length > 0) {
                mProgressBar.setProgress(values[0]);
            }
        }
    }
}

5. 下载文件动态更新进度条(封装)

Activity:

public class MainActivity extends Activity {

    private static final String FILE_NAME = "test.pdf";
    private static final String PDF_URL = "http://clfile.imooc.com/class/assist/118/1328281/AsyncTask.pdf";

    private ProgressBar mProgressBar;
    private Button mDownloadBtn;
    private TextView mStatus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        initView();
        setListener();
    }

    private void initView() {
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mDownloadBtn = (Button) findViewById(R.id.download);
        mStatus = (TextView) findViewById(R.id.status);
    }

    private void setListener() {
        mDownloadBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String localPath = Environment.getExternalStorageDirectory() + File.separator + FILE_NAME;
                DownloadHelper.download(PDF_URL, localPath, new DownloadHelper.OnDownloadListener() {
                    @Override
                    public void onStart() {
                        mDownloadBtn.setText("下载中");
                        mDownloadBtn.setEnabled(false);
                        mStatus.setText("下载中");
                        mProgressBar.setProgress(0);
                    }

                    @Override
                    public void onSuccess(File file) {
                        mDownloadBtn.setText("下载完成");
                        mStatus.setText(String.format("下载完成:%s", file.getPath()));
                    }

                    @Override
                    public void onFail(File file, String failInfo) {
                        mDownloadBtn.setText("开始下载");
                        mDownloadBtn.setEnabled(true);
                        mStatus.setText(String.format("下载失败:%s", failInfo));
                    }

                    @Override
                    public void onProgress(int progress) {
                        mProgressBar.setProgress(progress);
                    }
                });
            }
        });
    }


}

DownloadHelper:

class DownloadHelper {

    static void download(String url, String localPath, OnDownloadListener listener) {
        DownloadAsyncTask task = new DownloadAsyncTask(url, localPath, listener);
        task.execute();
    }

    private static class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {

        private String mFailInfo;

        private String mUrl;
        private String mFilePath;
        private OnDownloadListener mListener;

        DownloadAsyncTask(String mUrl, String mFilePath, OnDownloadListener mListener) {
            this.mUrl = mUrl;
            this.mFilePath = mFilePath;
            this.mListener = mListener;
        }

        @Override
        protected Boolean doInBackground(String... params) {
                String pdfUrl = mUrl;

                try {
                    URL url = new URL(pdfUrl);
                    URLConnection urlConnection = url.openConnection();
                    InputStream in = urlConnection.getInputStream();
                    int contentLength = urlConnection.getContentLength();

                    File pdfFile = new File(mFilePath);
                    if (pdfFile.exists()) {
                        boolean result = pdfFile.delete();
                        if (!result) {
                            mFailInfo = "存储路径下的同名文件删除失败!";
                            return false;
                        }
                    }

                    int downloadSize = 0;
                    byte[] bytes = new byte[1024];
                    int length;
                    OutputStream out = new FileOutputStream(mFilePath);
                    while ((length = in.read(bytes)) != -1) {
                        out.write(bytes, 0, length);
                        downloadSize += length;
                        publishProgress(downloadSize / contentLength * 100);
                    }

                    in.close();
                    out.close();

                } catch (IOException e) {
                    e.printStackTrace();
                    mFailInfo = e.getMessage();
                    return false;
                }
            return true;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (mListener != null) {
                mListener.onStart();
            }
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            if (mListener != null) {
                if (aBoolean) {
                    mListener.onSuccess(new File(mFilePath));
                } else {
                    mListener.onFail(new File(mFilePath), mFailInfo);
                }
            }
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (values != null && values.length > 0) {
                if (mListener != null) {
                    mListener.onProgress(values[0]);
                }
            }
        }
    }

    interface OnDownloadListener{
        void onStart();
        void onSuccess(File file);
        void onFail(File file, String failInfo);
        void onProgress(int progress);
    }
}
posted @ 2017-08-11 11:23  jyau  阅读(2282)  评论(1编辑  收藏  举报