2011-09-05 21:00:28
ZHUAZI : http://theron.blog.51cto.com/2383825/658455
AsyncTask 是Android为我们提供的另一种简单的异步线程机制。它可以比较方便的让我们的UI线程和后台线程并发,可以让用户执行一些需要长时间等待的程序时,用户体验不会因此而下降。
首先AsyncTask是一个抽象类,我们要使用它,必须写一个类来继承它。它有三个泛型参数,Param,Progress,Result,分别表示任务执行的参数,后台程序执行的进度和后台程序执行的结果。如果不提供参数,或者不使用进度,或者不需要结果,可以传入Void。同时,父类AsyncTask定义了若干方法,其中doInBackground=\'#\'" /div>
另外还有3个方法,分别是:
onPreExecute(),这个方法归属于UI线程,它执行于DoInBackgroud()之前,可以用作一些预处理,等会儿在例子中,我们使用这个方法来预处理进度条和百分比的显示初始化。
onPostExecute(Result),这个方法也归属于UI线程,他执行于doInBackgroud()之后,用于传递这个后台任务的执行结果。
onProgressUpdate(Progress...),这个方法同样归属于UI线程,它的执行与否,取决于DoInBackgroud()方法中是否使用了publishProgress方法,每次执行publishProgress方法,onProgressUpdate(Progress...)就会被调用一次。在这个方法中,通过publishProgress方法传来的进度信息,来更新UI信息。
需要注意的是,AsyncTask的子类的一个实例的生命周期从onPreExecute()开始,到onPostExecute(Result)结束,该实例之后就变成了垃圾,没用了。如果需要使用,就必须重新创建一个实例。
下面来看一个例子,这个例子实现的是一个进度条,从点击”Start”按钮开始进度条滚动。
布局文件很简单,一个开始按钮,一个进度条,和一个显示进度百分比的TextView
布局文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <Button
- android:id="@+id/start"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="Start"
- />
- <ProgressBar
- android:id="@+id/bar"
- android:layout_width="200dp"
- android:layout_height="wrap_content"
- style="?android:attr/progressBarStyleHorizontal"
- android:max="100"
- android:visibility="gone"
- />
- <TextView
- android:id="@+id/percent"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="10dp"
- android:text="0%"
- android:visibility="gone"
- android:layout_marginLeft="90dp"
- android:layout_marginTop="-18dp"
- android:textColor="#000"
- />
- </LinearLayout>
接下来看Java代码:
- import android.app.Activity;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- public class AsyncTaskDemoActivity extends Activity {
- private ProgressBar bar = null;
- private Button start = null;
- private TextView percent = null;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- start = (Button)findViewById(R.id.start); //Start按钮
- start.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- // TODO Auto-generated method stub
- SubAsyncTask sat = new SubAsyncTask(); //创建AsyncTask子类的实例
- sat.execute(); //启动线程
- }
- });
- }
- public class SubAsyncTask extends AsyncTask<Object, Integer, String>{
- @Override
- protected void onPreExecute() {
- // TODO Auto-generated method stub
- System.out.println("Thread in onPreExecute---->"+Thread.currentThread().getName());
- //在预处理方法中定义进度条和百分比文本
- bar = (ProgressBar)findViewById(R.id.bar);
- bar.setVisibility(View.VISIBLE);
- percent = (TextView)findViewById(R.id.percent);
- percent.setVisibility(View.VISIBLE);
- super.onPreExecute();
- }
- @Override
- protected String doInBackground(Object... arg0) {
- // TODO Auto-generated method stub
- //每50ms执行一次publishProgress
- for (int j = 0; j <=100; j+=10) {
- System.out.println("Thread in doInBackground---->"+Thread.currentThread().getName());
- publishProgress(j);
- try {
- Thread.sleep(50);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- return null;
- }
- @Override
- protected void onProgressUpdate(Integer... values) {
- // TODO Auto-generated method stub
- //每执行一次publishProgress就需要执行一次这个函数,在这个函数里变化进度条信息
- System.out.println("Thread in onProgressUpdate---->"+Thread.currentThread().getName());
- bar.setProgress(values[0]);
- percent.setText(values[0]+"%");
- }
- @Override
- protected void onPostExecute(String result) {
- // TODO Auto-generated method stub
- //doInBackground方法执行完后,执行这个函数,用来提交结果
- bar.setVisibility(View.GONE);
- percent.setVisibility(View.GONE);
- System.out.println("Thread in onPostExecute---->"+Thread.currentThread().getName());
- super.onPostExecute(result);
- }
- }
- }
从代码看出,我们并没有将
UI上得进度条控件和文本控件在onCreate函数中创建,而是只创建了一个开始Button,然后用匿名内部类为该Button绑定了一个事件监听器。在监听器内部,我们实例化了SubAsyncTask,SubAsyncTask是AsyncTask的子类,然后调用execute()方法来启动它。
重要的我们看
SubAsyncTask子类的实现。它继承了AsyncTask类并且重载了四个方法,也就是上面我提到的那四个方法。窝在每个方法内都设置了输出语句,查看当前的方法是哪个线程在执行。
作为预处理方法,我在
onPreExecute()方法中定义了进度条和百分比的TextView。当该函数执行完毕后,就开始执行doInBackground方法,在此方法中,我每隔50ms就执行一次publishProgress方法,这就意味着相应的,会有一个onProgressUpdate方法被调用,在onProgressUpdate方法中,我对进度条和进度百分比进行改变设置。当doInBackground方法运行完毕后,会自动执行onPostExecute方法,来提交执行的结果。
下图为运行的效果图:
下图是每隔
50ms,在Logcat中打印出来的记录,可以看出有两个线程在运行,一个是主线程,也就是UI线程,另一个是AsyncTask的线程。再看他们的输出顺序,可以发现,在更新进度条阶段,并不是规律的主线程与AsyncTask线程交替出现,也就说明,当AsyncTask线程更新进度条信息后,并没有等待UI线程更新UI,而是继续往下执行了,这也进一步体现了异步的特点。
如果将时间间隔改的更小,这种异步的输出就更明显了,下图是将时间间隔改为
10ms的Logcat输出。
AsyncTask比较方便的为我们提供了异步机制,可以有效的处理一些简单的
UI线程与后台线程的异步实现和交互。