AsyncTask
Android的UI线程主要负责处理用户的按键事件、用户触屏事件及屏幕绘制事件等,因此开发者的其它操作不应该也不能阻塞UI线程
为避免UI线程失去响应,Android建议将耗时操作放在新线程中完成,但新线程可能需要动态更新UI组件,而新线程是不允许直接更新UI组件的。
为解决新线程不能更新UI组件这一个问题,Android提供了如下方案:
- 使用Handler实现线程间通信
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
Handler处理已作说明,而后三种方式编程略显繁琐,而异步任务(AsyncTask)则可进一步简化这种操作
AsyncTask<Params, Progress, Result>是抽象类,它定义了如下三种泛型:
- Params:启动任务执行输入参数的类型
- Progress:后台任务完成的进度值类型
- Result:后台执行任务完成后返回结果的类型
使用AsyncTask的3个步骤:
- 创建AsyncTask子类,并为三个泛型参数指定类型(不需要的可指定为void)
- 据需要,实现AsyncTask的方法:
fun1:doInBackground(Params):重写该方法就是后台程序将要完成的任务,该方法可以调用publishProgress(Params..)更新任务执行进度
fun2:onProgressUpdate(Progress… value):在doInBackground()方法中调用publishProgress()更新进度后将触发该方法
fun3:onPreExecute():该方法将在执行后台耗时操作前被调用。通常用于完成一些初始化的操作,如在界面上显示进度条
fun4:onPostExecute(Result result):当doInBackground()完成后,系统会自动调用onPostExecute()方法,并将doInBackground方法的返回值传给该方法
3.调用AsyncTask子类的实例的execute(Params... params)开始执行耗时任务
使用AsyncTask时必须遵守如下规则:
1.必须在UI线程中创建AsyncTask实例
|
2.必须在UI线程中调用AsyncTask的execute()方法
|
3.AsyncTask的onPreExecute()、onPostExecute(Result result)、doInBackground(Params params),onProgressUpdate(Progress values)方法由Android系统负责调用
|
4.每个AsyncTask只能被执行一次,多次调用将会引发异常
|
示例代码如下:
public
class
MainActivity
extends
Activity {
private TextView show ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
show = (TextView) findViewById(R.id. show );
}
public void download(View source) throws MalformedURLException
{
DownTask task = new DownTask( this );
task.execute( new URL( "http:www.crazyit.org/ethos.php" ));
}
class DownTask extends AsyncTask<URL, Integer, String>
{
ProgressDialog pdialog ;
int hasRead = 0;
Context mContext ;
public DownTask(Context ctx)
{
mContext = ctx;
}
@Override
protected String doInBackground(URL... params)
{
StringBuilder sb = new StringBuilder();
try
{
URLConnection conn = params[0].openConnection();
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream()
, "utf-8" ));
String line = null ;
while ((line = br.readLine()) != null )
{
sb.append(line + '\n' );
hasRead ++;
publishProgress( hasRead );
// setProgress(hasRead);
}
return sb.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return null ;
}
@Override
protected void onPostExecute(String result)
{
show .setText(result);
pdialog .dismiss();
}
@Override
protected void onPreExecute()
{
pdialog = new ProgressDialog( mContext );
pdialog .setTitle( "mission executing" );
pdialog .setMessage( "processing , please wait" );
pdialog .setCancelable( false );
pdialog .setMax(202);
pdialog .setProgressStyle(ProgressDialog. STYLE_HORIZONTAL );
pdialog .setIndeterminate( false );
pdialog .show();
}
@Override
protected void onProgressUpdate(Integer...values )
{
show .setText( "has read " + values[0]+ "rows" );
pdialog .setProgress(values[0]);
}
}
private TextView show ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. activity_main );
show = (TextView) findViewById(R.id. show );
}
public void download(View source) throws MalformedURLException
{
DownTask task = new DownTask( this );
task.execute( new URL( "http:www.crazyit.org/ethos.php" ));
}
class DownTask extends AsyncTask<URL, Integer, String>
{
ProgressDialog pdialog ;
int hasRead = 0;
Context mContext ;
public DownTask(Context ctx)
{
mContext = ctx;
}
@Override
protected String doInBackground(URL... params)
{
StringBuilder sb = new StringBuilder();
try
{
URLConnection conn = params[0].openConnection();
BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream()
, "utf-8" ));
String line = null ;
while ((line = br.readLine()) != null )
{
sb.append(line + '\n' );
hasRead ++;
publishProgress( hasRead );
// setProgress(hasRead);
}
return sb.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return null ;
}
@Override
protected void onPostExecute(String result)
{
show .setText(result);
pdialog .dismiss();
}
@Override
protected void onPreExecute()
{
pdialog = new ProgressDialog( mContext );
pdialog .setTitle( "mission executing" );
pdialog .setMessage( "processing , please wait" );
pdialog .setCancelable( false );
pdialog .setMax(202);
pdialog .setProgressStyle(ProgressDialog. STYLE_HORIZONTAL );
pdialog .setIndeterminate( false );
pdialog .show();
}
@Override
protected void onProgressUpdate(Integer...values )
{
show .setText( "has read " + values[0]+ "rows" );
pdialog .setProgress(values[0]);
}
}
}
另外,程序需要使用网络,所以需要在android_manifest.xml文件中声明权限
<uses-permission android:name="android.permission.INTERNET"/>