Android消息处理机制之AsyncTask使用总结

一.异步任务AsyncTask的基本概念

       Android的AsyncTask轻量级简单的异步处理。
       首先明确Android之所以有Handler和AsyncTask,都是为了不阻塞主线程(UI线程),且UI 的更新只能在主线程中完成,因此异步处理是不可避免的。 Android为了降低这个开发难度,提供了AsyncTask。AsyncTask就是一个封装过的后台任务 类,顾名思义就是异步任务。 AsyncTask直接继承于Object类,位置为android.os.AsyncTask。
       要使用AsyncTask工作我 们要提供三个泛型参数,并重载几个方法(至少重载一个)。

(一)AsyncTask定义了三种泛型类型 Params,Progress和Result。

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

2.Progress 后台任务执行的百分比。

3.Result 后台执行任务最终返回的结果,比如String。

(二)使用AsyncTask异步任务最少要重写以下这两个方法:

1.doInBackground(Params…)

后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用 publicProgress(Progress…)方法来更新任务的进度。

2.onPostExecute(Result)

相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话你还得重写以下这三个方法,但不是必须的:

3.onPreExecute()

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

4.onProgressUpdate(Progress…)

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

5.onCancelled()

用户调用取消时,要做的操作

6. publicProgress(Progress…)方法

调用这个方法才能让onProgressUpdate(Progress…) 得到回调

(三)使用AsyncTask类,以下是几条必须遵守的准则:

1.Task的实例必须在UIthread中创建;

2.execute方法必须在UI thread中调用;

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

注意:AsyncTask只能被执行一次,否则多次调用时将会出现异常;

二.AsyncTask异步任务使用示例

程序实现功能:
从网络下载图片资源显示在GirdView布局中。

(一)布局文件设计

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="com.lwz.asyncTask.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="异步任务下载图片" />

    <GridView
        android:id="@+id/main_lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="2"
        ></GridView>
</RelativeLayout>

(二)java代码设计

package com.lwz.asyncTask;

import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * 使用异步任务来下载网路的多个图片,显示到ListView上
 * AsyncTask定义了三种泛型类型 Params,Progress和Result。
 * Params 启动任务执行的输入参数,比如HTTP请求的URL。
 * Progress 后台任务执行的百分比。
 * Result 后台执行任务最终返回的结果,比如String。
 */
public class MainActivity extends AppCompatActivity {

    //定义布局的控件
    GridView gridView;
    //数据源
    List<Bitmap> list = new ArrayList<>();

    //定义在异步任务中要下载的网络图片的Url的字符串
    String[] urls = {
            "http://i2.s2.dpfile.com/2011-08-31/9375230_b.jpg(700x700)/thumb.jpg"
            , "http://p11.aipai.com/photo/935/31233935/photo/213/2904277/2904277_normal.jpg"
            , "http://img5.duitang.com/uploads/item/201504/16/20150416H0755_LfSyA.jpeg"
            , "http://t-1.tuzhan.com/86ace0afc48f/c-2/l/2013/08/26/01/a28777d739b74b128f644e5eb136df88.jpg"
            , "http://www.bz55.com/uploads/allimg/130531/1-1305310Z505.jpg"
            ,"http://img1.gtimg.com/0/4/423/42385_1200x1000_0.jpg"
            ,"http://img1.gtimg.com/0/4/423/42385_1200x1000_0.jpg"
            ,"http://slides.discovery.tom.com/data1/upload/560/439/1262308559-202278983.jpg"
            ,"http://pic.xdnice.com/upload/2006_06/060625094611101.jpg"
            ,"http://www.junzimen.com/Article/UploadFiles/201105/2011051500590968.jpg"
            ,"http://www.artwork-cn.com/meitu/2015-11-27/0/2015112709001293030.jpg"
            ,"http://gameonline.yesky.com/uploadImages/2010/116/403791T007ND_1.jpg"
            ,"http://img1.cache.netease.com/catchpic/D/DA/DA6C8FDC0C5EF5800612BCA90033BCCF.jpg"
            ,"http://www.artwork-cn.com/meitu/2015-11-27/0/2015112708595783340.jpg"
            ,"http://photo.l99.com/bigger/20/1359108123916_m9u0pm.jpg"
            ,"http://www.dingbbs.com/uploads/allimg/1106/1_110607213326_14.jpg"
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //实例化ListView
        gridView = (GridView) findViewById(R.id.main_lv);
        //创建一个自己重写过的异步任务类
        MyAsyncTask asyncTask = new MyAsyncTask();
        //把数据传递给异步任务处理,这里传递的数据的类型和异步任务类的定义的第一个泛型数据类型是对应的
        asyncTask.execute(urls);
        //给ListView设置adapter对象
        gridView.setAdapter(adapter);
    }

    //创建内部类的adapter对象
    BaseAdapter adapter = new BaseAdapter() {
        @Override
        public int getCount() {
            return list.size();
        }

        @Override
        public Bitmap getItem(int position) {
            return list.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView iv = null;
            if (convertView == null) {
                iv = new ImageView(getBaseContext());
                convertView = iv;
            } else {
                iv = (ImageView) convertView;
            }
            //设置图片资源和属性
            iv.setImageBitmap(list.get(position));
            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            iv.setAdjustViewBounds(true);
            return iv;
        }
    };


    //在本类重写异步任务类
    class MyAsyncTask extends AsyncTask<String, Integer, List<Bitmap>> {
        //AsyncTask里面要传入三个泛型数据类别
        //第一个泛型代表的是要下载的图片的Url的字符串的数据类型,这里直接使用URL也是可以的
        //第二个泛型代表任务的进度值的数据类型,进度更新一般使用的是数值标识
        //第三个泛型代表的是异步任务完成时返回的结果的数据类型,返回的是一个图片资源,可以直接在页面上显示

        //定义一个进度条对象
        ProgressDialog progress;

        //在异步任务开始执行前的执行方法
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //这里显示一个进度条,进度在后面的方法中更新
            //实例化进度条对象
            progress = new ProgressDialog(MainActivity.this);
            //设置进度条的属性
            progress.setMessage("任务正在下载。。。");//设置主体内容
            progress.setTitle("图片下载");//设置标题栏
            progress.setMax(urls.length);//设置进度长度
            progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//设置水平的进度图形风格
            progress.setCancelable(false);//设置不可手动取消进度条,只能等任务下载完自动消失
            progress.show();

        }

        //这是在子线程中进行的运行的方法,做耗时任务,用于下载图片
        @Override
        protected List<Bitmap> doInBackground(String... params) {
            //这里的String和AsyncTask里传入的第一个泛型数据类别是一致的
            //params的数组数据需要在主线程中去输入

            //创建一个list结合来存放下载的数据
            List<Bitmap> bitmapList = new ArrayList<>();
            //获取每个Url,分别下载,处理,并添加到集合中
            for (int i = 0; i < params.length; i++) {
                //获取Url
                String path = params[i];
                try {
                    //下载图片
                    URL url = new URL(path);
                    //通过URL对象获取输入流
                    InputStream is = url.openStream();
                    //把输入流对象转换为Bitmap对象
                    Bitmap bitmap = BitmapFactory.decodeStream(is);
                    //给集合添加Bitmap对象
                    bitmapList.add(bitmap);
                    //更新进度的调用方法,里面参数的值是AsyncTask里传入的第二个泛型数据类别是一致的
                    publishProgress(i + 1);
                    Thread.sleep(1000);//每次加载图片后停一秒,看看下载过程
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return bitmapList;
        }

        //在publishProgress(i + 1)方法(在任务执行中)被调用之后的触发方法
        //在主线程中执行的操作
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //这里的数据values是publishProgress(i + 1);方法里面传递的数据
            //用来更新进度条的显示
            //这里值传入一个值所有使用values[0]就可以取得对应的值了
            progress.setProgress(values[0]);


        }

        //异步任务执行完毕后的回调方法
        //在主线程中执行的方法,可以直接把异步任务中的结果值,直接显示在UI页面
        @Override
        protected void onPostExecute(List<Bitmap> bitmaps) {
            super.onPostExecute(bitmaps);
            //把结果集赋值给ListView的数据源
            list = bitmaps;
            //刷新下适配器
            adapter.notifyDataSetChanged();
            //关闭进度条
            progress.cancel();
        }
    }

}

上面代码有异步任务使用过程的详细解释。
程序执行后显示的界面:
s1
任务完毕后,显示网络图片:
s2

       使用异步任务可以完成简单的信息传递。

       如果是比较复杂的信息传递,比如涉及到多个线程和多个消息的处理,就需要用到更加健壮的消息传送机制Handler来进行数据传送。Handler机制介绍在另一篇文章里面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值