AsyncTask异步任务总结

在实际应用中经常会遇到比较耗时任务的处理,比如网络连接,数据库操作等情况时,如果这些操作都是放在主线程(UI线程)中,则会造成UI的假死现象。臭名昭著的ANR(程序无响应)使得用户体验大打折扣。
在Android中,我们不希望耗时操作在主线程中完成,我们可以选择在子线程完成耗时操作,可是(系统规定)子线程又不允许直接控制主线程界面,即UI界面,完成了耗时操作,UI还是一动不动。为了解决这个矛盾,我们可以使用AsyncTask和Handler两种异步方式。
下面就AsyncTask相关介绍和用法做一下总结:

1.AsyncTask(异步任务)

Android的UI操作线程是不安全的;

(1)Android不建议我们在主线程进行耗时操作,(造成ANR程序无响应)(Application No Responsding)
(2)子线程中不能更新UI控件
(3)使用Handle通信机制实现子线程和主线程的通信
(4)AsyncTask已经帮我们封装好了子线程完成耗时操作,同时主线程中刷新UI

实现AsyncTask:

(1)只需要继承AsyncTask,并提供三个泛型,
(2)实现一系列的回调方法,实现子线程完成耗时操作,主线程刷新UI
(3)使用execute方法执行一个异步任务

2.如何使用AsyncTask?

(1)写一个类继承AsyncTask,并且提供了三个泛型

AsyncTask<Params,Progress,Result>

Params:启动异步任务时输入的参数类型
Progress:更新后台任务的进度的类型
Result:后台执行任务完成后返回结果的类型,doInbackground的返回值,这个值会传给onPostExecute()方法
例子:AsyncTask<String, Integer, byte[]>
在设置参数时通常是这样的:String… params,这表示方法可以有0个或多个此类型参数;有时参数可以设置为不使用,用Void…即可。

(2)AsyncTask重写的方法有四个

执行顺序:
1)onPreExecute():不必须重写的方法
在主线程中执行,首先执行
在doInBackground之前被调用
一般在子方法中做一些初始化操作
例子:ProgressDialog—>提示进度框

2)doInBackground(Params):必须重写的方法
在子线程中执行,交给系统(或AsyncTask)去调用,不用自己主动地去调用
所传的参数类型就是AsyncTask的第一个参数类型
publishProgress:通知AsyncTask进行任务进度更新

3)onProgressUpdate(Progress):(在doInBackground中调用publishProgress)
在主线程中执行
通知任务更新调用的方法
所传的参数类型就是AsyncTask的第二个参数类型

4)onPostExecute(Result):更新UI
在主线程中执行,需要根据 doInbackground返回的值刷新UI
在doInbackground方法执行完成后,被立即调用
所传的参数类型就是AsyncTask的第三个参数类型

四个方法:

1.onPreExecute()
执行预处理,它运行于UI线程,可以为后台任务做一些准备工作,比如绘制一个进度条控件。
2.doInBackground(Params…)
后台进程执行的具体计算在这里实现,doInBackground(Params…)是AsyncTask的关键,此方法必须重载。在这个方法内可以使用publishProgress(Progress…)改变当前的进度值。
3.onProgressUpdate(Progress…)
运行于UI线程。如果在doInBackground(Params…) 中使用了publishProgress(Progress…),就会触发这个方法。在这里可以对进度条控件根据进度值做出具体的响应。
4.onPostExecute(Result)
运行于UI线程,可以对后台任务的结果做出处理,结果就是doInBackground(Params…)的返回值。此方法也要经常重载,如果Result为null表明后台任务没有完成(被取消或者出现异常)。

举个例子:根据链接下载图片

package org.mobile.train.day07_qf_asynctask_download;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends Activity {

    private static final String IMAGE_URL = 
            "http://img1.imgtn.bdimg.com/it/u=1155447503,3876658488&fm=21&gp=0.jpg";

    private Button downloadImg;
    private ImageView image;

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

        downloadImg = (Button) findViewById(R.id.downloadImage);
        image = (ImageView) findViewById(R.id.image);
    }
    //button中定义的onClick属性,对应的方法
    public void downloadImg(View view) {
        //执行DownloadTask去完成下载图片
        new DownloadTask().execute(IMAGE_URL);
    }

    /**
     * 继承AsyncTask,实现子线程中下载网络图片,并在主线程中刷新UI
     * 第一个泛型:执行这个AsyncTask的时候所传的参数,这个参数会传给doInBackground(图片的URL)
     * 第二个泛型:可以用来更新后台任务的进度
     * 第三个泛型:doInBackground的返回值,这个值会传给onPostExecute
     *
     */
    public class DownloadTask extends AsyncTask<String, Integer, byte[]>{

        //任务进度的提示框
        ProgressDialog pd;

        /**
         * 在主线程中执行
         * 在doInBackground方法之前被调用
         * 一般在此方法中做一些初始化操作
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //初始化ProgressDialog
            pd = new ProgressDialog(MainActivity.this);
            //设置进度提示框的title
            pd.setTitle("提示");
            //设置进度提示框的提示信息
            pd.setMessage("正在下载中。。。");
            //显示ProgressDialog
            pd.show();
        }

        /**
         * 在子线程中执行, 这个方法交给系统去调用,不要自己主动的去调用
         * 所传的参数类型就是第一个泛型
         */
        @Override
        protected byte[] doInBackground(String... params) {
            String url = params[0];
            byte[] bytes = getImageFromInternet(url);
            return bytes;
        }

        /**
         * 在主线程中执行, 需要根据doInBackground返回的值,来刷新UI
         * 在doInBackground方法执行完之后,被立即调用
         */
        @Override
        protected void onPostExecute(byte[] result) {
            super.onPostExecute(result);
            //将一个byte[]转换成Bitmap
            Bitmap bm =BitmapFactory.decodeByteArray(result, 0, result.length);
            image.setImageBitmap(bm);
            //关闭进度提示框
            pd.dismiss();
        }

    }

    public byte[] getImageFromInternet(String url) {
        //定义输入流
        InputStream is = null;
        //保存图片数据的数组
        byte[] data = null;
        //定义一个输出流,
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        /**
         * 以下就是网络操作,下载图片
         */
        try {
            //定义URL
            URL imageUrl = new URL(url);
            //建立网络连接
            HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
            //解析网络请求
            if(conn != null && conn.getResponseCode() == 200) {
                //int totalLenght = conn.getContentLength();
                //int currentLength = 0;
                is = conn.getInputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while((len = is.read(buffer)) != -1){  //每次请求1KB
                    baos.write(buffer);
                    baos.flush();
                }
                data = baos.toByteArray();
                return data;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(baos != null)
                    baos.close();
                if(is != null)
                    is.close();
            } catch (Exception e2) {
            }
        }
        return null;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值