AsyncTask异步

一、简单理解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);
    }
}

猜你喜欢

转载自blog.csdn.net/weimeig/article/details/80266945