详解Android App中的AsyncTask异步任务执行方式
基本概念
asynctask:异步任务,从字面上来说,就是在我们的ui主线程运行的时候,异步的完成一些操作。asynctask允许我们的执行一个异步的任务在后台。我们可以将耗时的操作放在异步任务当中来执行,并随时将任务执行的结果返回给我们的ui线程来更新我们的ui控件。通过asynctask我们可以轻松的解决多线程之间的通信问题。
怎么来理解asynctask呢?通俗一点来说,asynctask就相当于android给我们提供了一个多线程编程的一个框架,其介于thread和handler之间,我们如果要定义一个asynctask,就需要定义一个类来继承asynctask这个抽象类,并实现其唯一的一个 doinbackgroud 抽象方法。要掌握asynctask,我们就必须要一个概念,总结起来就是: 3个泛型,4个步骤。
3个泛型指的是什么呢?我们来看看asynctask这个抽象类的定义,当我们定义一个类来继承asynctask这个类的时候,我们需要为其指定3个泛型参数:
asynctask <params, progress, result>
- params: 这个泛型指定的是我们传递给异步任务执行时的参数的类型
- progress: 这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给ui线程的参数的类型
- result: 这个泛型指定的异步任务执行完后返回给ui线程的结果的类型
我们在定义一个类继承asynctask类的时候,必须要指定好这三个泛型的类型,如果都不指定的话,则都将其写成void,例如:
asynctask <void, void, void>
4个步骤:当我们执行一个异步任务的时候,其需要按照下面的4个步骤分别执行
- onpreexecute(): 这个方法是在执行异步任务之前的时候执行,并且是在ui thread当中执行的,通常我们在这个方法里做一些ui控件的初始化的操作,例如弹出要给progressdialog
- doinbackground(params... params): 在onpreexecute()方法执行完之后,会马上执行这个方法,这个方法就是来处理异步任务的方法,android操作系统会在后台的线程池当中开启一个worker thread来执行我们的这个方法,所以这个方法是在worker thread当中执行的,这个方法执行完之后就可以将我们的执行结果发送给我们的最后一个 onpostexecute 方法,在这个方法里,我们可以从网络当中获取数据等一些耗时的操作
- onprogressupdate(progess... values): 这个方法也是在ui thread当中执行的,我们在异步任务执行的时候,有时候需要将执行的进度返回给我们的ui界面,例如下载一张网络图片,我们需要时刻显示其下载的进度,就可以使用这个方法来更新我们的进度。这个方法在调用之前,我们需要在 doinbackground 方法中调用一个 publishprogress(progress) 的方法来将我们的进度时时刻刻传递给 onprogressupdate 方法来更新
- onpostexecute(result... result): 当我们的异步任务执行完之后,就会将结果返回给这个方法,这个方法也是在ui thread当中调用的,我们可以将返回的结果显示在ui控件上
为什么我们的asynctask抽象类只有一个 doinbackground 的抽象方法呢??原因是,我们如果要做一个异步任务,我们必须要为其开辟一个新的thread,让其完成一些操作,而在完成这个异步任务时,我可能并不需要弹出要给progressdialog,我并不需要随时更新我的progressdialog的进度条,我也并不需要将结果更新给我们的ui界面,所以除了doinbackground 方法之外的三个方法,都不是必须有的,因此我们必须要实现的方法是 doinbackground 方法。
实例
下面实现一个打开网络图片的demo:
package com.app.main; import org.apache.http.httpentity; import org.apache.http.httpresponse; import org.apache.http.client.httpclient; import org.apache.http.client.methods.httpget; import org.apache.http.impl.client.defaulthttpclient; import org.apache.http.util.entityutils; import android.annotation.suppresslint; 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.view.view.onclicklistener; import android.widget.button; import android.widget.imageview; public class main extends activity { string url = "http://e.hiphotos.baidu.com/image/w%3d2048/sign=61711bd121a446237ecaa262ac1a730e/e850352ac65c10385f10af69b3119313b07e892a.jpg"; imageview imgview = null; button btn = null; progressdialog dialog = null; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); imgview = (imageview) this.findviewbyid(r.id.imageview); btn = (button) this.findviewbyid(r.id.btn); dialog = new progressdialog(this); dialog.setmessage("下载图片中......"); btn.setonclicklistener(new onclicklistener() { @override public void onclick(view view) { new mytask().execute(url); } }); } class mytask extends asynctask<string, void, bitmap> { @override protected void onpreexecute() { super.onpreexecute(); dialog.show(); } @override protected bitmap doinbackground(string... params) { bitmap bitmap = null; string url = params[0]; httpclient client = new defaulthttpclient(); httpget getmethod = new httpget(url); try { httpresponse response = client.execute(getmethod); if (response.getstatusline().getstatuscode() == 200) { httpentity entity = response.getentity(); byte[] data = entityutils.tobytearray(entity); bitmap = bitmapfactory .decodebytearray(data, 0, data.length); } } catch (exception e) { } return bitmap; } @suppresslint("newapi") @override protected void onpostexecute(bitmap result) { super.onpostexecute(result); imgview.setimagebitmap(result); dialog.dismiss(); } } }
实现的效果如图: