一.简介
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();
}
}
}
}
}