AsyncTask入门(二)

在它的代码中,AsyncTask是你拓展的一个抽象类,和提供用于一个耗时的异步任务的基本框架。
最恰当的一个描述AsyncTask的方式是把它当作一个工作线程三明治。也就是说,它有三个主要的方法可以提供给你实现。

  • onPreExecute 发生在主线程,是它的第一片面包干。它建立任务,准备载入对话框,和提醒用户将要发生的事。

  • onInBackground 是这个小任务三明治的肉饼(也是必要的)。这个方法是由安卓保障的在分离的后台线程运行。这是你的工作发生的主要地方。

  • onPostExcecute 会在你工作一完成时调用(也是在主线程中),并且产生的结果是由后台方法传递的。这是另一片面包干。

这就是异步任务的要领。还有更多复杂因素,但这是安卓平台基本构建区块之一。

大概看一看,等下我们会讲述其中的细节

private class ImageDownloader extends AsyncTask<String, Integer, Bitmap>{

   Override
   protected void onPreExecute(){
     //设置是在这里完成的
   }

   @Override
   protected Bitmap doInBackground(String... params) {
      try{
         URL url = new URL(params[0]);
         HttpURLConnection httpCon =
      (HttpURLConnection) url.openConnection();

       if(httpCon.getResponseCode() != 200)
          throw new Exception("Failed to connect");
       }

       InputStream is = httpCon.getInputStream();
       return BitmapFactory.decodeStream(is);

       }catch(Exception e){
         Log.e("Image","Failed to load image",e);
       }
       return null;
   }
 @Override
   protected void onProgressUpdate(Integer... params){
      //在这里更新进度条,或者忽略它,这取决于你的需要
   }
   @Override
   protected void onPostExecute(Bitmap img){
      ImageView iv = (ImageView) findViewById(R.id.remote_image);
      if(iv!=null && img!=null){
         iv.setImageBitmap(img);
      }
   }
   @Override
   protected void onCancelled(){
      // 处理你要做的事,如果你取消这个任务
   }
}

这是一个异步任务会下载一张图片在任意链接后,并显示(需要你提供有一个叫remote_image ID的图片组件在在你的屏幕上)下面是你如何在你的Activity中从onCreate()方法启动任务。

public void onCreate(Bundle extras){
   super.onCreate(extras);
   setContentView(R.layout.image_layout);

   ImageDownloader imageDownloader = new ImageDownloader();
   imageDownloader.execute("http://wanderingoak.net/bridge.png");
}

一旦你在ImageDownloader中调用execute()方法,它就会下载图片,处理成为一个bitmap,然后展示在屏幕上。那就是,假设在你的image_layout.xml文件中包含一个叫做remote_image的ImageView组件。

如何使它按照你的要求工作

AsyncTask需要你指定三个范型参数在继承的任务声明中。

  • 这参数类型会被传进类中。在这个例子中,我传进一个url的字符串,但我也可以传入多个这样的字符串。parameter总会被引用为一个数组不管你传入多少个参数。注意到了吗,我使用params[0]引用单个url字符串.

  • doInBackground方法(主线程之下)和onProgressUpdate方法(在主线程调用)之间传递的对象。在这个例子中没有使用到,因为我没有做任何进程更新,但它很可能是一个整形数据,可能是完成情况的百分比或者是所传递的字节数。

  • doInBackground方法返回的对象会被onPostExecute方法调用处理。在这个例子中,它是我们目标下载的图片(bitmap).

这是三个对象声明的行:

private class ImageDownloader extends AsyncTask<String, Integer, Bitmap>{}

在例子中,这些是会传进你的三个主要方法的类。
onPreExecute

protected void onPreExecute(){}

onPreExecute()方法通常是当你想要建立一个加载对话框或者加载下拉列表在屏幕的某一角。记住,onPreExecute实在主线程调用,所以请不要在这个方法中触及文件系统或联网。

doInBackground

protected Bitmap doInBackground(String... params) {}

这个是你的机会去实现尽可能多的联网,文件系统访问或者其它长时间的操作而不用干等手机。传进这个方法的对象类型是在你的AsyncTask类声明所决定的一个泛型对象类型。尽管在例子中我只使用了一个参数,但事实上你可传入任意数量的参数(只要他们派生于已存在的类),你就可以在doInBackground方法调用时取到他们。一旦长时间运行的任务完成,你可能需要返回结果在你方法题的最后。这个最终值会传入另一个回调在主UI线程上的方法。

显示你的任务进程
AsyncTask有其它方面你应该注意到的,尽管我没有演示出来。在doInBackground里,你可以发送进度更新给用户界面。doInBackground不在主线程上,所以当你想要更新进度栏或者改变屏幕上某对象的状态时,你得返回到主线程完成这些改变。

protected void onProgressUpdate(Integer... params){
   //在这里更新进度条或者忽略它,这取决于你的需要
}

一如既往地,请小心使用UI更新,因为如果活动不在当前屏幕或者已经被摧毁,你会碰到一些麻烦。

onPostExecute
这个事务完成时,或者,如例子中的,图片已经下载好了。是时候更新屏幕使用我已获得的内容。在doInBackground 的最后,如果成功,我返回一个已加载的图片(bitmap)给AsyncTask.
现在安卓会切换到主线程并且调用onPostExecute 方法,传递我在doInBackground 最后返回的类型。下面就是那个代码:

protected void onPostExecute(Bitmap img){
   ImageView iv = (ImageView)findViewById(R.id.remote_image);
   if(iv!=null && img!=null){
      iv.setImageBitmap(img);
   }
}

我取得网上下载的图片(bitmap),取回要加载的图片组件,设置它作为组件图片来呈现。有一个错误例子我还没有正确处理,再看一下源码,看是否能找出来。

一些重要的注意事项

通常地,一个AsyncTask 是从活动中启动的。然而,你必须记得的是活动有短的生命周期。回想下,默认地,安卓摧毁(destroy )和重建(reCreate)任意活动在你每次的屏幕回转。安卓也会摧毁你的活动,当用户退出它。你可能有理由问:”如果我从一个活动中启动一个AsyncTask,然后该活动被摧毁,会发生什么?你猜:这非常糟糕。尝试去画一个活动已经从屏幕上被摧毁会造成所有方式的灾难(通常会时一个未处理的异常)

跟踪你启动的任意AsyncTask是一个好主意,当活动调用onDestroy 方法时,确保调用cancel方法在任何遗留的AsyncTask。

这里有两个推荐情况能让AsyncTask完美胜任这个任务:

  • 下载少量数据时具体到一个特定的活动

  • 从外置内存驱动载入文件(通常是SD卡)

确保你移动的AsyncTask的数据只属于某一个活动,因为你的任务一般不该跨越多个。你可以在活动间传递它如果屏幕切换,但这可能非常棘手。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值