什么是AsyncTask
AsyncTask是安卓提供的一个抽象类,有助于我们更好地使用UI线程。它允许我们执行耗时或后台的操作并将结果展示在UI线程而不必操作线程。
何时使用AsyncTask
安卓实现的是单线程模型,每当启动安卓应用,一个线程就会被创建。假设我们正要做联网操作在我们的应用程序按钮上,一点击这个按钮,一个请求就会被发送给服务器,而且回复会被等待。由于安卓的单线程模式,直到等待时间先被响应否则我们的屏幕都是非响应的。所以我们需要避免执行长时间的操作在UI线程。包括文件访问和联网访问。
为了解决这个问题,我们可以创建一个新线程和实现run()方法去执行网络调用。所以这时的UI任然能响应操作。
但是因为安卓采用单线程模式,而且安卓UI工具包不是线程安全的。因此基于执行结果的需要,UI有必要做些改变,然后这个方式可能会产生一些问题。
故而安卓框架有一个非常棒的模式包裹成AsyncTask。
注意:
AsyncTask理应用于那些只花时几秒的操作。有一些任务需要线程运行较长时间的建议使用 java.util.concurrent 包里的例如 Executor ThreadPoolExecutor and FutureTask
AsyncTask有下面四个步骤:
1. doInBackground:代码在这个方法中执行长时间的操作,当点击按钮执行onClick()方法,它调用执行方法接收参数并自动调用带传入参数的doInBackground方法。
2. onPostExecute :这个方法在doInBackground方法完成处理后被调用。来自doInBackground的结果会被传入到这个方法中。
3. onPreExecute :这个方法在doInBackground 方法调用前先调用。
4. onProgressUpdate : 这个方法被调用在doInBackground 方法调用publishProgress 任何时候。
这个任务可以被取消当调用cancel(boolean)方法。这会产生一连串的调用,isCancelled()返回真,在调用这个方法后,onCancelled(Object)被调用而不是onPostExecute()在doInBackground()方法返回后。
怎样使用AnycTask?举个例子
在案例应用中我只是让线程休眠一段时间而不是进行联网操作。(只是解释AsyncTask的概念,这不是一个实际的应用程序)。在UI线程输入一个值(以毫秒为单位),这会传递给AsyncTaskRunner。AsyncTaskRunner是一个继承AsyncTask的私有类。
当用户点击Run Async Task按钮,我们让线程休眠一段时间。同时我们在UI线程响应展示这个状态给用户。
完成这个过程后,将最终结果展示给用户。
下面是创建这个应用的步骤
- 在ecilpse创建一个默认设置的安卓项目
- 创建应用的布局
- 创建MainActivity 并在com.example.asynctaskdemo.MainActivity.java下创建AsyncTaskRunner
- 运行结果如上图所给截屏
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10pt"
android:textColor="#444444"
android:layout_alignParentLeft="true"
android:layout_marginRight="9dip"
android:layout_marginTop="20dip"
android:layout_marginLeft="10dip"
android:text="Sleep time in milliseconds:"/>
<EditText
android:id="@+id/et_time"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background"
android:layout_toRightOf="@id/tv_time"
android:layout_alignTop="@id/tv_time"
android:inputType="text"
/>
<Button
android:id="@+id/btn_do_it"
android:layout_width="200dip"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginTop="15dip"
android:layout_marginLeft="260dip"
android:layout_below="@id/et_time"
android:text="Run Async task" />
<TextView
android:id="@+id/tv_result"
android:layout_width="400dip"
android:layout_height="100dip"
android:textSize="7pt"
android:layout_alignParentLeft="true"
android:layout_below="@id/btn_do_it"
android:layout_marginRight="9dip"
android:layout_marginTop="15dip"
android:layout_marginLeft="260dip"
android:textColor="#AA0000"
android:text=""/>
</RelativeLayout>
MainActivity.java
package com.example.asynctaskdemo;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
/**
* @author Prabu
* AsyncTask exmple
*
*/
public class MainActivity extends Activity {
private Button button;
private EditText time;
private TextView finalResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
time = (EditText) findViewById(R.id.et_time);
button = (Button) findViewById(R.id.btn_do_it);
finalResult = (TextView) findViewById(R.id.tv_result);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AsyncTaskRunner runner = new AsyncTaskRunner();
String sleepTime = time.getText().toString();
runner.execute(sleepTime);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
/**
* @author Prabu
* Private class which runs the long operation. ( Sleeping for some time )
*/
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
@Override
protected String doInBackground(String... params) {
publishProgress("Sleeping..."); // Calls onProgressUpdate()
try {
// Do your long operations here and return the result
int time = Integer.parseInt(params[0]);
// Sleeping for given time period
Thread.sleep(time);
resp = "Slept for " + time + " milliseconds";
} catch (InterruptedException e) {
e.printStackTrace();
resp = e.getMessage();
} catch (Exception e) {
e.printStackTrace();
resp = e.getMessage();
}
return resp;
}
/*
* (non-Javadoc)
*
* @see android.os.AsyncTask#onPostExecute(java.lang.Object)
*/
@Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
finalResult.setText(result);
}
/*
* (non-Javadoc)
*
* @see android.os.AsyncTask#onPreExecute()
*/
@Override
protected void onPreExecute() {
// Things to be done before execution of long running operation. For
// example showing ProgessDialog
}
/*
* (non-Javadoc)
*
* @see android.os.AsyncTask#onProgressUpdate(Progress[])
*/
@Override
protected void onProgressUpdate(String... text) {
finalResult.setText(text[0]);
// Things to be done while execution of long running operation is in
// progress. For example updating ProgessDialog
}
}
}