android的异步加载与UI

原帖地址: http://blog.163.com/freemanls@126/blog/static/16458506120117702029517/

android的异步加载与UI  

2011-08-07 12:55:27|  分类: Android |  标签:android  异步  图片   |字号 订阅

前言

今天我们探讨的内容是andorid中的异步,同时就异步问题对UI进行联合探讨。

         本章内容希望读者熟悉java基础,对线程有熟悉。


        

         我们知道,java中的线程是指异步,也就是在主程序进行的同时,副程序也在进行(比喻)。Java中,实现异步一般使用2种方法,一种是实现接口Runable,一种是继承类Thread。不过这不是我们今天要讨论的内容,上面的所的东西只是你应该知道并且了解的东西。今天我们讲述的重点是android的异步。

         Android中,异步实现,一般用handler和AsyncTask,通常handler是一个消息栈,而AsyncTask不是。

         我们今天将的是AsyncTask作为异步的教学。你会问了,为啥不用handler?具体的我们可以看如下解释:

         “很多网友可能发现Android平台很多应用使用的都是AsyncTask,而并非Thread和Handler去更新UI,这里给大家说下他们到底有什么区别,我们平时应该使用哪种解决方案。从Android 1.5开始系统将AsyncTask引入到android.os包中,过去在很早1.1和1.0 SDK时其实官方将其命名为UserTask,其内部是JDK 1.5开始新增的concurrent库,做过J2EE的网友可能明白并发库效率和强大性,比Java原始的Thread更灵活和强大,但对于轻量级的使用更为占用系统资源。Thread是Java早期为实现多线程而设计的,比较简单不支持concurrent中很多特性在同步和线程池类中需要自己去实现很多的东西,对于分布式应用来说更需要自己写调度代码,而为了Android UI的刷新Google引入了Handler和Looper机制,它们均基于消息实现,有事可能消息队列阻塞或其他原因无法准确的使用。

 

Android开发网推荐大家使用AsyncTask代替Thread+Handler的方式,不仅调用上更为简单,经过实测更可靠一些,Google在Browser中大量使用了异步任务作为处理耗时的I/O操作,比如下载文件、读写数据库等等,它们在本质上都离不开消息,但是AsyncTask相比Thread加Handler更为可靠,更易于维护,但AsyncTask缺点也是有的比如一旦线程开启即dobackground方法执行后无法给线程发送消息,仅能通过预先设置好的标记来控制逻辑,当然可以通过线程的挂起等待标志位的改变来通讯,对于某些应用Thread和Handler以及Looper可能更灵活。”

        

         当然 handler+Thread方式我们还是会讲解的,届时大家也可以看到一个对比。

 

AsyncTask初识

         我在做一个图片管理器,在图片展示的时候,出现了很多问题,其中最重要的问题就是用户体验:比如九宫图的时候,我最开始使用的是同步代码进行图片加载,结果30多张图片让我等了10秒,当然,就算算上读出图片进行处理的过程,这个时间我也不能接受。

         异步可以在一定程度上减轻这部分的延迟,提高用户体验,它的思路是:即时加载图片,即时更新图片列表。所以我在九宫图的时候,可以看到图片的一张一张刷新——这就是异步操作。

         OK。我们知道android的后台是java写的,我们可以用Thread跟Runalbe来实现异步,在java中,他们确实是异步,但是我们今天是要异步更换UI界面的东西。做过系统的人可能知道(我也是看别人的博客知道的),任何UI的更新必须在activity主线程中进行,因为这样才能保证一定的安全(这一部分我也不是非常了解,为了不误导各位,请大家看其他资料,我也会持续补充的)。

         那么Android是怎么解决的呢?用handler+Thread/Runable或者AsyncTask,他们是activity主线程中“伪造”的线程,并不见得分配线程ID给他们,所以能够更新!我们今天使用AsyncTask进行异步图片的讲解,同时,对于handler的异步,我想我会用一个幻灯片的例子,来给自己和大家一个交代。

        

AsyncTask的代码结构

         之前我们将过AsyncTask是用来做异步的。我也说过将异步的图片即时加载到UI上去——怎么加载?

         我们先用文字描述下AsyncTask的入参和内部的方法——我们会用到的或者说比较常用的方法。

1)         入参

我们一般用一个类来定义一个异步。比如下面这种

class AsyncTaskLoad extends AsyncTask<Object, Bitmap, Object>

我们看到了有3个入参,他们分别是

l  Params, the type of the parameters sent to the task upon execution.

l  Progress, the type of the progress units published during the background computation.

l  Result, the type of the result of the background computation.

上面是对此的解释

l  递交给异步处理的入参

l  在更新时候或者处理时候的入参

l  返回结果

我来解释下第二条,我们在后台处理过后,需要即时通知UI更新,调用的方法的入参。如果不明白,之后的代码会详细说明的。

2)         方法

继承了AsyncTask,默认要实现的方法是doInBackground:

@Override

       protected Object doInBackground(Object... params)

       这货就是后台异步的逻辑处理,比如我们的图片,在数据库中抓取、处理就是在这里写的。同时当我们是一个循环的时候,我们会在里面写一段话调用更新方法,这句话是:

       // 在此提醒前台九宫图更新,此时原图应该也刷出来了

       publishProgress(bitmap);

       恩,我说下,bitmap是一个Bitmap的实例化。我们调用的方法入参是Bitmap型的(跟类声明联系一起,第二个入参),他会调用方法:

       @Override

       protected void onProgressUpdate(Bitmap... values) {

           // TODO Auto-generated method stub

           // super.onProgressUpdate(values);

           /* 将数据放入adapter中,并且通知页面UI刷新 */

           for (Bitmap bitmap : values) {

              // 添加内容到adapter

              imageAdapter.addPhoto(bitmap);

              // 通知页面UI刷新数据

              imageAdapter.notifyDataSetChanged();

           }

       }     

恩,这就是我们的更新方法。我们看到方法入参是一个Bitmap,这个定义是在类继承的时候第二个入参定义的。入参为Bitmap... values,这你可以理解为

Bitmap[] values,更多资料请查略资料,这个不提了。

内容是循环values,第一个是将位图添加到适配器adapter中,另一个notifyDataSetChanged就是一个关键点,他通知adapter本身数据更新了,你应该更新UI展示。

 

我们完成异步图片加载,基本来说就只需要上面2个方法就可以做到。但是AsyncTask还有一些方法,我们需要知晓,他们分别是:

@Override

       protected void onPostExecute(Object result)

                   异步结束操作,我们看到入参是我们类继承方法定义的Object

@Override

protected void onPreExecute() {

// TODO Auto-generated method stub

super.onPreExecute();

}

异步逻辑处理前操作(doInBackground方法执行前)。

 

onPreExecute,onPostExecute,以及onProgressUpdate都可以对UI进行操作,他们的不同处是在异步执行的先后次序不一样。onPreExecute是先逻辑执行,onProgressUpdate是逻辑中执行,onPostExecute是异步逻辑完全执行完毕后执行。

 

 

代码和其他说明

基本上也讲完了,接下来就是贴代码了,使用115网盘。

http://u.115.com/file/clqcacyn

代码实现的功能是:

?  完成九宫图的异步加载;

?  完成点击九宫图,显示点击的图片序列号。

来一张截图

(原创)android的异步加载与UI - 梁生 - 梁生的窝
 

需要提下的是,我的代码是通过在sdcard中获取图片,如果要运行代码,请预先配置好资源,否则启动报错。关于android的sd卡配置,网上有很多资料的。顺便提下,如果要结合eclipse进行,请选用elipse伽利略版以上版本的。要不启动sdcard会比较麻烦。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章