android中,为了避免UI线程阻塞,失去响应的问题,建议将耗时的操作放在新的线程中执行,但是,在新的线程中不允许直接更新UI,那么我们该如何解决呢?比如这样一个实例:我需要执行一个耗时的操作A,在A结束后才刷新当前页面UI,但又不希望用户感觉到这个等待的时间存在,这时,我们该如何解决呢?

android中,提供了几种方案:

,使用Handler实现线程通信;
,使用AsyncTask;
,Activity.runOnUiThread(Runnable);
,View.post(Runnable);

Handler,大家可能并不陌生,而AsyncTask相比Handler而言,更轻量级一些,不需要借助Handler和Thread即可实现UI刷新;对于3,4两种方法,比较繁琐,因此,这里主要介绍一下异步操作。

AsyncTask刷新UI的例子太少,而且前篇一律的都是网络资源下载的一个例子,今天,我们介绍一个新的例子,就针对开始的那个耗时操作的问题来说吧。

HorizontalScrollView加载多个ImageView显示图像的功能,而图像的加载需要执行耗时操作,比如对每个图像都进行一些图像处理变换等,然后加载到HorizontalScrollView中显示,假如我直接在主线程中进行,那么用户可能会有个图像刷新等待时间,假如每张图像处理100ms,那么20张图像就2s了,等到20张图像一起处理完了再更新UI,这个时间会严重影响用户体验效果,因此,我把这个图像处理刷新,放在一个异步任务中执行,这样,20张图像是一次刷新出来,用户体验上是很快的连续刷出来的20张图像,每次刷新时间间隔是100ms,效果明显不一样了。

  下面我们就构建这样一个异步类:

class ThumbnailGenerateTask extends AsyncTask<Integer, Integer, Bitmap> {
        private ImageView imageView;
        private int id = 0;//imageView的索引
        public ThumbnailGenerateTask(ImageView imgView) {
      super();
            imageView = imgView;//初始化
        }

        @Override

        protected void onPreExecute() {

            super.onPreExecute();//完成一些初始化工作,在执行后台耗时操作前被调用

        }

        @Override

        protected Bitmap doInBackground(Integer... params) {

            // TODO Auto-generated method stub

            Bitmap bmp = null;

            try {

                id = params[0]; //参数根据自己需要进行传递

                bmp = BitmapFactory.decodeResource(res, R.drawable.test);   //耗时的图像处理操作            
            } catch (Exception e) {
                return null;
            }
            return bmp;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);//此处可用于更新进度条
        }

        @Override

        protected void onPostExecute(Bitmap result) {

            if (result != null&&imageView!=null) {

                imageView.setScaleType(ScaleType.CENTER_CROP);//刷新后的结果图像就是result,将其赋值给响应的imageview即可完成UI刷新

                imageView.setImageBitmap(result);

                thumbnail[id].setImageBitmap(result);

                thumbnail[id].setScaleType(ScaleType.FIT_XY);

            } else {
                this.cancel(true);
            }
            super.onPostExecute(result);
        }

    调用代码如下:

public class MainActivity extends Activity {

private HorizontalScrollView scrollView = null;

private Resources res = null;

private LinearLayout filterLinearLayout = null;

private ImageView[]thumbnail = null;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        scrollView = (HorizontalScrollView)findViewById(R.id.scrollView);

        scrollView.setHorizontalScrollBarEnabled(false);

        filterLinearLayout = (LinearLayout)findViewById(R.id.linearLayout);

        filterLinearLayout.setHorizontalScrollBarEnabled(true);

        res = this.getResources();

        thumbnail = new ImageView[]{(ImageView)findViewById(R.id.img1),(ImageView)findViewById(R.id.img2),(ImageView)findViewById(R.id.img3),

  
        for(int i=1;i<=7;i++)
        {
            ThumbnailGenerateTask task = new ThumbnailGenerateTask(thumbnail[i-1]);//为每一次刷新定制异步任务

            task.execute(i-1);

        }

    }

 执行这个程序,你就会发现,图像时一张一张刷新出来的,而不是等待一段时间后一下刷新的!异步任务其实就是把ThumbnailGenerateTask 这个类中的框架按照你的需求填满而已,这个实例非常简单,相信大家能看的明白