1. 不要阻塞UI线程
2. 确保只在UI线程中访问Android UI工具包
当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,
如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。
但是,当我们涉及到比较耗时的操作,例如访问网络,读写数据库或文件等时,一般都是需要再开一个线程,
android提供了几种在其他线程中访问UI线程的方法。
Activity.runOnUiThread( Runnable )
View.post( Runnable )
View.postDelayed( Runnable, long )
Hanlder
这些类或方法同样会使你的代码很复杂很难理解,然而当你需要实现一些很复杂的操作并需要频繁地更新UI时这会变得更糟糕。
下面我们介绍一个在安卓中比较常用且轻量级的线程辅助类:AsyncTask。它使创建需要与用户界面交互的长时间运行的任务变得更简单。
AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果。
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。
1) 子类化AsyncTask
2) 实现AsyncTask中定义的下面一个或几个方法
onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
例子:我们保存数据到数据库中去,将保存部分的代码放到doInBackground(后台线程执行方法)中,保存的时候弹出
一个对话框,给用户相应的提示信息,保存完毕,将对话框关闭,部分代码如下:
ProgressDialog progressDialog = ProgressDialog.show(
this,
getString(R.string.tip),
getString(R.string.saving));
/**
* 第一个泛型:控制doInBackground的参数类型
* 第三个泛型:控制doInBackground的返回值类型和onPostExecute的参数类型
* doInBackground的返回值类型会传给onPostExecute当参数
*/
AsyncTask task = new AsyncTask<Void, Void, Integer>() {
/**
* 在后台线程中调用doInBackground
*/
@Override
protected Integer doInBackground(Void... params) {
//保存到数据库
ContentValues values = new ContentValues();
values.put(Contact.NAME, nameText);
values.put(Contact.PHONE, phoneText);
values.put(Contact.PHOTO, selectedId);
values.put(Contact.ADDRESS, addressText);
long id = mgr.add(values);
return (int)id;
}
/**
* 当doInBackground执行完毕后,回到主线程调用onPostExecute
*/
@Override
protected void onPostExecute(Integer result) {
//关闭对话框
progressDialog.dismiss();
if(result > 0){//保存成功
//toast(R.string.save_success);
//说明要刷新
setResult(CODE_REFRESH);
finish();
}else{//保存失败
toast(R.string.save_error);
}
}
};
//执行异步任务,execute参数会传给doInBackground方法
task.execute(new Void[]{});