AsyncTask详解

AsyncTask详解

为什么要异步任务

Android为了解决UI线程的阻塞引入了Handler机制和AsyncTask

  1. Android是单线程模型。在android中只有主线程能够对UI进行操作,而其他线程不能对UI进行操作。这样就保证了UI的稳定性和准确性,避免多个线程同时操作,造成UI混乱。
  2. 耗时操作放在非主线程中执行。比如网络操作或读取文件,如果放在主线程中执行,那么就会造成后面任务的阻塞,就用可能产生ANR,影响用户体验。

Asynctask

  1. 线程中更新UI。
  2. 封装和简化了异步操作。只是操作上简化,效率上并没有。

AsyncTask是抽象类,它定义了三种泛型类型 Params,Progress和Result

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。
  • Progress 后台任务执行的百分比。
  • Result 后台执行任务最终返回的结果类型,比如String。

使用AsyncTask主要有三步

  1. 创建AsyncTask的子类,并为三个泛型参数赋值。根据需要,可以设置为Void。
  2. 根据需要实现如下方法:
    • onPreExecute(): 该方法在执行后台耗时操作前被主线程(UI线程)调用。常用来初始化工作,如显示进度条等。
    • doInBackground(Params…): 在onPreExecute() 方法执行后马上执行,完成耗时操作,在异步线程中执行,不能操作UI。可以调用 publishProgress方法来更新实时的任务进度。抽象方法,必须实现。
    • onProgressUpdate(Progress…): 在doInBackground(Params…)调用publishProgress方法后触发该方法,被主线程调用在界面上展示任务的进展情况,例如通过一个进度条进行展示。
    • onPostExecute(Result):在doInBackground(Params…)完成后,得到doInBackground(Params…)的返回值,用来操作UI界面。
  3. 调用AsyncTask子类实例的execute(Params…)来开启异步任务。

一个网络加载图片的例子

创建一个image.xml,简单布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
 android:layout_width="match_parent"  
android:layout_height="match_parent"  
android:padding="16dp">  
<ImageView
    android:id="@+id/imageView"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    />
<ProgressBar
    android:id="@+id/progressBar"
    android:visibility="gone"
    android:layout_centerInParent="true"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    />
 </RelativeLayout>

ImageDownloadTest.java

package com.qbc.asynctaskdemo;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import java.net.URL;

public class ImageDownloadTest extends Activity {
private ImageView myImg;
private ProgressBar progressBar;
private static String URL ="http://image.cnwest.com/attachement" +
        "/jpg/site1/20110303/001372d899ef0ed99b635c.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.image);
    myImg= (ImageView) findViewById(R.id.imageView);
    progressBar= (ProgressBar) findViewById(R.id.progressBar);
    MyAsyncTask myAsyncTask=new MyAsyncTask();
    myAsyncTask.execute(URL);//启动AsyncTask,并把参数传递给doInBackground()
}
//创建AsyncTask类
//三个参数分别是URL、进度值和返回值,返回一张图片
class MyAsyncTask extends AsyncTask<String,Void,Bitmap>{
    @Override//这个方法在执行耗时操作前被调用。常用来初始化准备工作
    protected void onPreExecute() {
        super.onPreExecute();
        progressBar.setVisibility(View.VISIBLE);//将布局中隐藏的progressbar显示出来
    }
    @Override//
    protected Bitmap doInBackground(String... params) {//这个方法开启异步线程执行耗时操作
        String url=params[0];//获取参数
        Bitmap bitmap=null;
        URLConnection conn;
        InputStream inputStream;
        try {
            conn=new URL(url).openConnection();
            inputStream=conn.getInputStream();
            BufferedInputStream bis =new BufferedInputStream(inputStream);
            //网络太快看不出效果,让它睡一下,真机调试可以去掉。
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            bitmap= BitmapFactory.decodeStream(bis);
            inputStream.close();
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;//返回一张图片给onPostExecute(Bitmap bitmap)
    }
    @Override
    protected void onPostExecute(Bitmap bitmap) {
        super.onPostExecute(bitmap);
        progressBar.setVisibility(View.GONE);//任务完成,隐藏进度条
        myImg.setImageBitmap(bitmap);//显示图片
    }
}

}

模拟进度条

progressbar.xml很简单。

public class ProgressBarDemo extends Activity {
private ProgressBar mProgressBar;
private ProgressBarAsyncTask mTask=null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.progressbar);
    mProgressBar= (ProgressBar) findViewById(R.id.progressBar);
    mTask=new ProgressBarAsyncTask();
    mTask.execute();
}

@Override
protected void onPause() {
    super.onPause();
    //cancel()只是将对应的AsyncTask标记为cancel状态,并没有真正的取消AsyncTask任务的执行。
    //还需要去监测它的改变,然后执行相应操作
    if(mTask!=null && mTask.getStatus()==AsyncTask.Status.RUNNING){
        mTask.cancel(true);
    }
}
class ProgressBarAsyncTask extends AsyncTask<Void,Integer,Void>{
    @Override
    protected Void doInBackground(Void... params) {
        for(int i=0;i<100;i++){
            if(mTask.isCancelled()){//监听task是否为cancel状态
                break;
            }
            publishProgress(i);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        mProgressBar.setProgress(values[0]);
    }
}
}

在onPause()中调用mTask.cancel(true),将对应的AsyncTask标记为cancel状态,然后在doInBackground中调用mTask.isCancelled()进行监听task状态,为cancel状态就break,结束任务,这样就可以使得AsyncTask和Activity的生命周期一样长,反复退出重进的时候就不会等待上一个任务的结束,而是重新开始任务。可以去掉onPause()方法进行测试对比。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值