AsyncTask详解

一.简介

AsyncTask是Android提供的轻量级异步类,可以直接继承AsyncTask,在类中实现异步操作,最后反馈执行的结果给UI主线程。实现 子线程 & 主线程(UI线程)之间的通信

 

 

 

 

 

 

 

二.AsyncTask实现类步骤

 

AsyncTask是一个抽象类

public abstract class AsyncTask<Params, Progress, Result>

 

1.自定义类 继承 AsyncTask抽象类。

public class MyAsyncTasks extends AsyncTask<String, Integer, String> {
    
    ...
    
    @Override
    protected String doInBackground(String... strings) {
        return null;
    }
}

doInBackground()方法 是必须重写的方法。

 

 

2.重写其他常用的方法

package com.dchealth.patient.XinSui.test;

import android.os.AsyncTask;

public class MyAsyncTasks extends AsyncTask<String, Integer, String> {

    /**
     * 该方法UI线程运行 准备工作
     */

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 该方法子线程运行,主要用于异步操作或者耗时操作
     */

    @Override
    protected String doInBackground(String... strings) {
        return null;
    }

    /**
     * 该方法UI线程中执行 主要用于更新进度条(下载进度)
     */

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    /**
     * 该方法UI线程当中执行 主要用于更新UI
     */

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }

}

 

 

3.AsyncTask调用

String url="";
MyAsyncTasks myAsyncTasks = new MyAsyncTasks();
myAsyncTasks.execute(url);

 

 

4.AsyncTask关闭

AsyncTask在执行多个线程时,是单个执行,其它线程是在缓冲区。当执行完一个下一个才开始。当然也为了内存问题。所以当使用AsyncTask时,要在一定的时候关闭AsyncTask。

 

Activity页面页面销毁

@Override
protected void onDestroy() {
    super.onDestroy();
    if (null != myAsyncTasks && myAsyncTasks.getStatus() == MyAsyncTasks.Status.RUNNING) {
        myAsyncTasks.cancel(true);
        myAsyncTasks = null;
    }
}

注意:重要

本以为调用task.cancel(true)就可以强制结束AsyncTask。但是实际上是不可行的,因为task.cancel(true)方法仅仅是将AsyncTask的cancel标识符设置为true,仍然需要去手动停止循环。具体方法见下:

 

onPostExecute方法

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    if(isCancelled()){//已取消直接return 不执行该方法中的代码
        return;
    }


    ...dosomething
}

 

onProgressUpdate方法 

@Override
protected void onProgressUpdate(Integer... values) {
    super.onProgressUpdate(values);
    if(isCancelled()){//已取消直接return 不执行该方法中的代码
        return;
    }

    ...dosomething
}

 

doInBackground方法

@Override
protected String doInBackground(String... strings) {
    if(isCancelled()){//已取消直接return 不执行该方法中的代码
        return "";
    }


    return strings[0];
}

 

 

5.AsyncTask总结

<1> AsyncTask定义了三种泛型类型 Params,Progress和Result。

Params:启动任务执行的输入参数,比如HTTP请求的URL

Progress后台任务执行的百分比

Result:后台执行任务最终返回的结果,比如String报文

 

<2> 使用AsyncTask至少要重写以下这两个方法

doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在子线程执行,完成任务的主要工作,通常需要较长的时间。

 

onPostExecute(Result):相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回。

 

有必要的话你还得重写以下这三个方法,但不是必须的:

 

onProgressUpdate(Progress…):可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。

 

onPreExecute():这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。

 

onCancelled() :用户调用取消时,要做的操作。

 

 

<3> 使用AsyncTask类,以下是几条必须遵守的准则:

(1) Task的实例必须在主线程创建

(2) execute方法必须在主线程调用

(3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法。

(4) 同一个AsyncTask实例对象只能执行1次,若执行第2次将会抛出异常。

 

 

 

 

 

 

三.Demo实现

 

1.简单Demo

 

AsyncTask实现类

package com.dchealth.patient.XinSui.test;

import android.os.AsyncTask;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MyAsyncTasks extends AsyncTask<String, Integer, String> {

    private ProgressBar progressBar;
    private TextView resultTextView;

    public MyAsyncTasks(ProgressBar progressBar, TextView resultTextView) {
        this.progressBar = progressBar;
        this.resultTextView = resultTextView;
    }

    /**
     * 该方法UI线程运行 准备工作
     */

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    /**
     * 该方法子线程运行,主要用于异步操作或者耗时操作
     */

    @Override
    protected String doInBackground(String... strings) {
        if (!isCancelled()) {
            try {
                int count = 0;
                int length = 1;
                while (count < 99) {
                    count += length;
                    // 可调用publishProgress()显示进度, 之后将执行onProgressUpdate()
                    publishProgress(count);
                    // 模拟耗时任务
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("TAG", "doInBackground方法 已停止!");
        }
        return "结果完成";//此处的return ""字符串 将更新到onPostExecute方法
    }

    /**
     * 该方法UI线程中执行 主要用于更新进度条(下载进度)
     */

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        if (!isCancelled()) {
            progressBar.setProgress(values[0]);
        } else {
            Log.d("TAG", "onProgressUpdate方法 已停止!");
        }
    }

    /**
     * 该方法UI线程当中执行 主要用于更新UI
     */

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (!isCancelled()) {
            resultTextView.setText("结果:" + s);
        } else {
            Log.d("TAG", "onPostExecute方法 已停止!");
        }
    }

}

 

Activity代码

package com.dchealth.patient.XinSui.test;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.dchealth.patient.XinSui.R;

public class MyActivity extends AppCompatActivity {

    private ProgressBar progressBar;
    private TextView resultTextView;
    private TextView textView;
    private TextView textViews;
    private MyAsyncTasks myAsyncTasks;

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

    /**
     * 初始化各种View
     */

    private void initView() {
        progressBar = findViewById(R.id.activity_my_progressbar);
        resultTextView = findViewById(R.id.activity_my_resulttextview);
        textView = findViewById(R.id.activity_my_textview);
        textViews = findViewById(R.id.activity_my_textviews);

        myAsyncTasks = new MyAsyncTasks(progressBar, resultTextView);

        //开始
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String url = "";
                myAsyncTasks.execute(url);
            }
        });

        //结束
        textViews.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myAsyncTasks.cancel(true);
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != myAsyncTasks && myAsyncTasks.getStatus() == MyAsyncTasks.Status.RUNNING) {
            myAsyncTasks.cancel(true);
            myAsyncTasks = null;
        }
    }

}

 

 

 

2.AsyncTask+EventBus实现下载CSV文件Demo

 

AsyncTask实现类

/**
 * 任务列表下载CSV文件AsyncTask
 */

public class DownLoadRenWuTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;
    private ProgressDialog procDialog;
    private String filename;

    /**
     * 构造方法
     */

    public DownLoadRenWuTask(Context context, ProgressDialog procDialog, String filename) {
        this.context = context;
        this.procDialog = procDialog;
        this.filename = filename;
    }

    /**
     * doInBackground方法 后台执行耗时方法 下载文件
     */

    @Override
    protected String doInBackground(String... sUrl) {
        if (isCancelled()) {//已取消直接return 不执行该方法中的代码
            return "已取消";
        }

        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {//响应失败
                return "server returned HTTP:" + connection.getResponseCode() + "" + connection.getResponseMessage();
            }
            int fileLength = connection.getContentLength();
            input = connection.getInputStream();
            if (BooleanUtils.isEmpty(filename)) {
                filename = System.currentTimeMillis() + ".csv";
            }
            output = new FileOutputStream(FileHelper.getTheRootDirectory() + StringConstant.RenWu_Path + filename);
            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                if (fileLength > 0) {
                    //publishing hte progress...
                    publishProgress((int) (total * 100 / fileLength));
                    output.write(data, 0, count);
                }
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (null != output) {
                    output.close();
                }
                if (null != input) {
                    input.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (null != connection) {
                connection.disconnect();
            }
        }

        return null;
    }

    /**
     * onPreExecute方法 准备工作
     */

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        if (isCancelled()) {//已取消直接return 不执行该方法中的代码
            return;
        }

        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
        mWakeLock.acquire();
        procDialog.show();
    }

    /**
     * onProgressUpdate方法 更新进度
     */

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        if (isCancelled()) {//已取消直接return 不执行该方法中的代码
            return;
        }

        procDialog.setIndeterminate(false);
        procDialog.setMax(100);
        procDialog.setProgress(progress[0]);
    }

    /**
     * onPostExecute方法 更新结果
     */

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        if (isCancelled()) {//已取消直接return 不执行该方法中的代码
            return;
        }
        
        mWakeLock.release();
        procDialog.dismiss();
        //发送EventBus通知 刷新任务详情模块
        EventBusBean eventBusBean = new EventBusBean();
        eventBusBean.setUpdatetype(result);
        eventBusBean.setContext(filename);
        EventBus.getDefault().post(eventBusBean);
    }

}

 

Activity

/**
 * 下载CSV文件
 * */

private void loadCSVFile(){
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setMessage("文件下载");
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    mProgressDialog.setCanceledOnTouchOutside(false);
    
    downloadTask = new DownLoadRenWuTask(this, mProgressDialog,filepath);
    downloadTask.execute(url);
    
    mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
        @Override
        public void onCancel(DialogInterface dialog) {
            downloadTask.cancel(true);
        }
    });
}



/**
 * onEventMainThread EventBus
 */
 
public void onEventMainThread(EventBusBean eventBusBean) {
    if (null != eventBusBean) {
        String type = eventBusBean.getUpdatetype();
        String filepath = eventBusBean.getContext();
        if(!BooleanUtils.isEmpty(type)){
            toast.showToast(StringConstant.renwuststatus10);
        } else {
                if(!BooleanUtils.isEmpty(filepath)&&null!=file&&!BooleanUtils.isEmpty(createfile)){
                boolean isExist = FileHelper.isExistFile(file, filepath);
                if (isExist) {//文件已存在
                    showViewData(createfile,filepath);
                    toast.showToast(StringConstant.renwuststatus5);
                } else {//文件 不存在
                    loadCSVFile();
                }
            }
        }
    }
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值