原CSDN博客已弃用,文章会逐渐迁移过来。

一、简单理解Demo

    import android.app.Activity;  
import android.os.AsyncTask;  
import android.os.Bundle;  

public class MainActivity extends Activity {  

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

        /* 
         * 运行TestAsyncTask 
         */  
        new TestAsyncTask().execute();  
    }  

    private class TestAsyncTask extends AsyncTask{  

        //一般用于初始化,首先运行  
        @Override  
        protected void onPreExecute() {  
            // TODO Auto-generated method stub  
            super.onPreExecute();  
        }  
        //一般处理耗时操作,第二运行,不要在这里面运行与ui控件有关的操作  
        @Override  
        protected Object doInBackground(Object... params) {  
            return null;  
        }  
        /* 
         * 一般用于处理UI界面变化,最后运行 
         * result是上面doInBackground返回值 
         */  
        @Override  
        protected void onPostExecute(Object result) {  
            // TODO Auto-generated method stub  
            super.onPostExecute(result);  
        }  



    }  


}  

二、实践熟悉Demo
activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    >  
    <TextView  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="Hello , Welcome to Andy's Blog!"/>  
    <Button  
        android:id="@+id/download"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="Download"/>  
    <TextView  
        android:id="@+id/tv"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="当前进度显示"/>  
    <ProgressBar  
        android:id="@+id/pb"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        style="?android:attr/progressBarStyleHorizontal"/>  
</LinearLayout>  

MainActivity.java

    import android.app.Activity;  
import android.os.AsyncTask;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import android.widget.ProgressBar;  
import android.widget.TextView;  

public class MainActivity extends Activity {  

    Button download;  
    ProgressBar pb;  
    TextView tv;  

    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        pb=(ProgressBar)findViewById(R.id.pb);  
        tv=(TextView)findViewById(R.id.tv);  

        download = (Button)findViewById(R.id.download);  
        download.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                DownloadTask dTask = new DownloadTask();  
                dTask.execute(100);  
            }  
        });  
    }  

    class DownloadTask extends AsyncTask<Integer, Integer, String>{  
        //后面尖括号内分别是参数(例子里是线程休息时间),进度(publishProgress用到),返回值 类型  

        @Override  
        protected void onPreExecute() {  
            //第一个执行方法  
            super.onPreExecute();  
        }  

        @Override  
        protected String doInBackground(Integer... params) {  
            //第二个执行方法,onPreExecute()执行完后执行  
            for(int i=0;i<=100;i++){  
                pb.setProgress(i);  
                publishProgress(i);  
                try {  
                    Thread.sleep(params[0]);  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
            return "执行完毕";  
        }  

        @Override  
        protected void onProgressUpdate(Integer... progress) {  
            //这个函数在doInBackground调用publishProgress时触发,虽然调用时只有一个参数  
            //但是这里取到的是一个数组,所以要用progesss[0]来取值  
            //第n个参数就用progress[n]来取值  
            tv.setText(progress[0]+"%");  
            super.onProgressUpdate(progress);  
        }  

        @Override  
        protected void onPostExecute(String result) {  
            //doInBackground返回时触发,换句话说,就是doInBackground执行完后触发  
            //这里的result就是上面doInBackground执行后的返回值,所以这里是"执行完毕"  
            setTitle(result);  
            super.onPostExecute(result);  
        }  

    }  
}  

三、简单学习Demo

activity.xml使用系统默认即可,

Java学习代码如下

MainActivity.java

package com.administrator.asynctaskdemo;  

import android.os.AsyncTask;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.util.Log;  

public class MainActivity extends AppCompatActivity {  
    private static final String TAG = "MainActivity";//键盘在空白处输入logt,AndroidStudio会快速生成这行代码  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  

//        new DownloadAsyncTask().execute("XueXi","KanShu");  
        new DownloadAsyncTask().execute("XueXi");  
    }  

    public class DownloadAsyncTask extends AsyncTask<String,Integer,Boolean>{  
        /** 
         * 在异步任务之前,在主线程中 
         */  
        @Override  
        protected void onPreExecute() {  
            super.onPreExecute();  
            //可操作UI  
        }  

        /** 
         * 在另外一个线程中处理事件 
         * @param params 入参 
         * @return 结果 
         */  
        @Override  
        protected Boolean doInBackground(String... params) {//String... strings表示长度是可变参数,  
                                                            // 比如外部调用时,doInBackground("a");doInBackground("a","b");  
                                                            // doInBackground("a","b","c");等,参数的数量是可变的  
            for (int i = 0;i<10000;i++){  
                Log.i(TAG,"doInBackground:"+params[0]);  
                //抛出进度  
                publishProgress(i);  
            }  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            return true;  
        }  

        @Override  
        protected void onPostExecute(Boolean aBoolean) {  
            super.onPostExecute(aBoolean);  
            //也是在主线程中,执行结果处理  
        }  

        @Override  
        protected void onProgressUpdate(Integer... values) {  
            super.onProgressUpdate(values);  
            //收到上面抛出的进度,然后处理:也是在UI线程中  
        }  

//        @Override  
//        protected void onCancelled() {  
//            super.onCancelled();  
//        }  
//  
//        @Override  
//        protected void onCancelled(Boolean aBoolean) {  
//            super.onCancelled(aBoolean);  
//        }  
    }  
}  

四、AsyncTask实现异步下载
步骤
1.网络上请求数据:申请网络权限 读写存储权限
2.布局我们的layout
3.下载之前我们要做什么? UI
4.下载中我们要做什么? 数据
5.下载后我们要做什么? UI

在MainManifest.xml中申请网络权限和读写权限

    <uses-permission android:name="android.permission.INTERNET"/>  
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>  
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

activity_main

    <?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:id="@+id/activity_main"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:padding="10dp"  
    android:orientation="vertical"  
    tools:context="com.administrator.asynctaskdemo.MainActivity">  


    <ProgressBar  
        style="?android:attr/progressBarStyleHorizontal"  
        android:layout_width="match_parent"  
        android:layout_height="15dp"  
        android:id="@+id/progressBar"/>  

    <Button  
        android:text="点击下载"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:id="@+id/button"/>  

    <TextView  
        android:text="Hello world! imooc."  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:id="@+id/textView"/>  

</LinearLayout>  

MainActivity.java

    package com.administrator.asynctaskdemo;  

import android.os.AsyncTask;  
import android.os.Environment;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.Button;  
import android.widget.ProgressBar;  
import android.widget.TextView;  

import org.w3c.dom.Text;  

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.net.URL;  
import java.net.URLConnection;  

/** 
 * 1.网络上请求数据:申请网络权限 读写存储权限 
 * 2.布局我们的layout 
 * 3.下载之前我们要做什么?  UI 
 * 4.下载中我们要做什么?  数据 
 * 5.下载后我们要做什么? UI 
 */  
public class MainActivity extends AppCompatActivity {  
    private static final String TAG = "MainActivity";//键盘在空白处输入logt,AndroidStudio会快速生成这行代码  
    public static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";  
    private ProgressBar mProgressBar;  
    private Button mDownloadButton;  
    private TextView mResultTextView;  
    private int INIT_PROGRESSBAR;  
    private String FILE_NAME = "XueXi.apk";  

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

        //初始化视图  
        initView();  
        //设置点击监听  
        setListener();  
        //初始化UI数据  
        setData();  

    }  

    private void setListener() {  
        mDownloadButton.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                //TODO 18/5/10 下载任务  
                DownloadAsyncTask asyncTask = new DownloadAsyncTask();  
                asyncTask.execute(APK_URL);  
            }  
        });  
    }  

    private void setData() {  
        mProgressBar.setProgress(INIT_PROGRESSBAR);  
        mDownloadButton.setText("点击下载");  
        mResultTextView.setText("准备下载");  
    }  

    /** 
     * 初始化视图 
     */  
    private void initView() {  
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);  
        mDownloadButton = (Button) findViewById(R.id.button);  
        mResultTextView = (TextView) findViewById(R.id.textView);  
    }  


    /** 
     * String 入参 
     * Integer 进度 
     * Boolean 返回值 
     */  
    public class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {  
        String mFilePath;  
        /** 
         * 在异步任务之前,在主线程中 
         */  
        @Override  
        protected void onPreExecute() {  
            super.onPreExecute();  
            //可操作UI  类似淘米,之前的准备工作  
            mDownloadButton.setText("下载中");  
            mResultTextView.setText("下载中");  
            mProgressBar.setProgress(INIT_PROGRESSBAR);  
        }  

        /** 
         * 在另外一个线程中处理事件 
         * 
         * @param params 入参  煮米 
         * @return 结果 
         */  
        @Override  
        protected Boolean doInBackground(String... params) {//String... strings表示长度是可变参数,  
            if(params != null&¶ms.length>0){  
                String apkUrl = params[0];  
                try {  
                    //构造URL  
                    URL url = new URL(apkUrl);  
                    //构造连接,并打开  
                    URLConnection urlConnection = url.openConnection();  
                    InputStream inputStream =urlConnection.getInputStream();  
                    //获取下载内容的总长度  
                    int contentlength = urlConnection.getContentLength();  
                    //下载地址准备  

                    mFilePath = Environment.getExternalStorageDirectory()   //  File.separator是字符串/  
                            + File.separator + FILE_NAME;  

                    //对下载地址进行处理  
                    File apkFile = new File(mFilePath);  
                    if(apkFile.exists()){  
                        boolean result = apkFile.delete();  
                        if(!result){ //如果失败了  
                            return false;  
                        }  
                    }  

                    //已下载的大小  已下载大小/总长度*100等于下载进度  
                    int downloadSize = 0;  

                    //byte数组  
                    byte[] bytes = new byte[1024];  
                    int length;  

                    //创建一个输入管道  
                    OutputStream outputStream = new FileOutputStream(mFilePath);  
                    length = inputStream.read(bytes);  

                    //不断的一车一车挖土,直到挖不倒为止  
                    while ((length = inputStream.read(bytes))!= -1){  
                        //挖到的放到我们的文件管道里  
                        outputStream.write(bytes,0,length);  
                        //累加我们的大小  
                        downloadSize += length;  
                        //发送进度  
                        publishProgress(downloadSize*100/contentlength);  
                    }  
                    inputStream.close();  
                    outputStream.close();  

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

            return true;  
        }  

        @Override  
        protected void onPostExecute(Boolean result) {  
            super.onPostExecute(result);  
            //也是在主线程中,执行结果处理  
            mDownloadButton.setText(result?"下载完成"+ mFilePath:"下载失败");  
            mResultTextView.setText(result?"下载完成"+ mFilePath:"下载失败");  
        }  

        @Override  
        protected void onProgressUpdate(Integer... values) {  
            super.onProgressUpdate(values);  
            //收到进度,然后处理:也是在UI线程中  
            if(values!=null&&values.length>0){}  
            mProgressBar.setProgress(values[0]);  
        }  
    }  

}  

五、封装成工具类

xml布局如上不变

创建下载工具类

DownloadHelper.java

    package com.administrator.asynctaskdemo;  

import android.os.AsyncTask;  

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.net.URL;  
import java.net.URLConnection;  

/** 
 * 1.download方法  url localPath listener 
 * 2.listener :start success fail progress 
 * 3.用asynctask封装 
 * Created by Administrator on 2018/5/10. 
 */  

public class DownloadHelper {  
    public static void download(String url,String localPath,OnDownloadListener listener) {  
        DownloadAsyncTask task = new DownloadAsyncTask(url,localPath,listener);  
        task.execute();  
    }  
        /** 
         * String 入参 
         * Integer 进度 
         * Boolean 返回值 
         */  
        public static class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> {  
            String mUrl;  
            String mFilePath;  
            OnDownloadListener mListener;  

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

            /** 
             * 在异步任务之前,在主线程中 
             */  
            @Override  
            protected void onPreExecute() {  
                super.onPreExecute();  
                //可操作UI  类似淘米,之前的准备工作  
                if(mListener != null){  
                    mListener.onStart();  
                }  
            }  

            /** 
             * 在另外一个线程中处理事件 
             * 
             * @param params 入参  煮米 
             * @return 结果 
             */  
            @Override  
            protected Boolean doInBackground(String... params) {//String... strings表示长度是可变参数,  
                    String apkUrl = mUrl;  
                    try {  
                        //构造URL  
                        URL url = new URL(apkUrl);  
                        //构造连接,并打开  
                        URLConnection urlConnection = url.openConnection();  
                        InputStream inputStream =urlConnection.getInputStream();  
                        //获取下载内容的总长度  
                        int contentlength = urlConnection.getContentLength();  

                        //对下载地址进行处理  
                        File apkFile = new File(mFilePath);  
                        if(apkFile.exists()){  
                            boolean result = apkFile.delete();  
                            if(!result){ //如果失败了  
                                if(mListener != null){  
                                    mListener.onFail(-1,apkFile,"文件删除失败");  
                                }  
                                return false;  
                            }  
                        }  

                        //已下载的大小  已下载大小/总长度*100等于下载进度  
                        int downloadSize = 0;  

                        //byte数组  
                        byte[] bytes = new byte[1024];  
                        int length;  

                        //创建一个输入管道  
                        OutputStream outputStream = new FileOutputStream(mFilePath);  
                        length = inputStream.read(bytes);  

                        //不断的一车一车挖土,直到挖不倒为止  
                        while ((length = inputStream.read(bytes))!= -1){  
                            //挖到的放到我们的文件管道里  
                            outputStream.write(bytes,0,length);  
                            //累加我们的大小  
                            downloadSize += length;  
                            //发送进度  
                            publishProgress(downloadSize*100/contentlength);  
                        }  
                        inputStream.close();  
                        outputStream.close();  

                    } catch (IOException e) {  
                        e.printStackTrace();  
                        if(mListener != null){  
                            mListener.onFail(-2,new File(mFilePath),e.getMessage());  
                        }  
                        return false;  
                    }  

                if(mListener != null){  
                        mListener.onSuccess(0,new File(mFilePath));  
                }  
                return true;  
            }  

            @Override  
            protected void onPostExecute(Boolean result) {  
                super.onPostExecute(result);  
                //也是在主线程中,执行结果处理  
                if (mListener != null){  
                    if(result){  
                        mListener.onSuccess(0,new File(mFilePath));  
                    }else {  
                        mListener.onFail(-1,new File(mFilePath),"下载失败");  
                    }  
                }  
            }  

            @Override  
            protected void onProgressUpdate(Integer... values) {  
                super.onProgressUpdate(values);  
                //收到进度,然后处理:也是在UI线程中  
                if(values!=null&&values.length>0){  
                    if(mListener != null){  
                        mListener.onProgress(values[0]);  
                    }  
                }  
            }  
        }  


    public interface OnDownloadListener{  
        void onStart();  
        void onSuccess(int code,File file);  
        void onFail(int code,File file,String message);  
        void onProgress(int progress);  

        /** 
         * 如果加写下面这个子类实现了OnDownloadListener的抽象方法,则外部创建该接口时,如通过 
         * new DownloadHelper.OnDownloadListener.SimpleDownloadListener()调用该方法时, 
         * 不需要每次都重写已在SimpleDownloadListener类中实现的onStart()和onProgress()这两个方法 
         */  
        abstract class SimpleDownloadListener implements OnDownloadListener{  
            @Override  
            public void onStart() {  

            }  

            @Override  
            public void onProgress(int progress) {  

            }  
        }  
    }  
}  

外部调用

MainActivity.java

    package com.administrator.asynctaskdemo;  

import android.os.AsyncTask;  
import android.os.Environment;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.util.Log;  
import android.view.View;  
import android.widget.Button;  
import android.widget.ProgressBar;  
import android.widget.TextView;  

import org.w3c.dom.Text;  

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.net.URL;  
import java.net.URLConnection;  
import java.time.LocalDate;  

/** 
 * 1.网络上请求数据:申请网络权限 读写存储权限 
 * 2.布局我们的layout 
 * 3.下载之前我们要做什么?  UI 
 * 4.下载中我们要做什么?  数据 
 * 5.下载后我们要做什么? UI 
 */  
public class MainActivity extends AppCompatActivity {  
    private static final String TAG = "MainActivity";//键盘在空白处输入logt,AndroidStudio会快速生成这行代码  
    public static final String APK_URL = "http://download.sj.qq.com/upload/connAssitantDownload/upload/MobileAssistant_1.apk";  
    private ProgressBar mProgressBar;  
    private Button mDownloadButton;  
    private TextView mResultTextView;  
    private int INIT_PROGRESSBAR;  
    private String FILE_NAME = "XueXi.apk";  

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

        //初始化视图  
        initView();  
        //设置点击监听  
        setListener();  
        //初始化UI数据  
        setData();  

    }  

    private void setListener() {  
        mDownloadButton.setOnClickListener(new View.OnClickListener() {  
            @Override  
            public void onClick(View v) {  
                //TODO 18/5/10 下载任务  
                DownloadHelper.download(APK_URL," ", new DownloadHelper.OnDownloadListener.SimpleDownloadListener() {  
                    @Override  
                    public void onSuccess(int code, File file) {  
                        Log.e("TAG",String.valueOf(code));  
                    }  

                    @Override  
                    public void onFail(int code, File file, String message) {  
                        Log.e("TAG",String.valueOf(code));  
                        Log.e("TAG",message);  
                    }  
                });  
            }  
        });  
    }  

    private void setData() {  
        mProgressBar.setProgress(INIT_PROGRESSBAR);  
        mDownloadButton.setText("点击下载");  
        mResultTextView.setText("准备下载");  
    }  

    /** 
     * 初始化视图 
     */  
    private void initView() {  
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);  
        mDownloadButton = (Button) findViewById(R.id.button);  
        mResultTextView = (TextView) findViewById(R.id.textView);  
    }  
}