AsyncTask学习笔记

AsyncTask定义了三种泛型类型 Params,Progress和Result。

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。
  • Progress 后台任务执行的百分比。
  • Result 后台执行任务最终返回的结果,比如String。



使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

  • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
  • onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回



有必要的话你还得重写以下这三个方法,但不是必须的:

  • onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
  • onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
  • onCancelled() 用户调用取消时,要做的操作



使用AsyncTask类,以下是几条必须遵守的准则:

  • Task的实例必须在UI thread中创建;
  • execute方法必须在UI thread中调用;
  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
  • 该task只能被执行一次,否则多次调用时将会出现异常;
最后记住:
  1. 这些方法中,只有doInBackground(Params…)是在新线程中执行,其它所有方法都是在主线程(即UI线程)中执行的
  2. 函数关系:抓住三个泛型之间的关系,这里的函数都是通过泛型来联系的:Params 、Progress 、Result 。比如:

    • AsyncTask入口execute(params)参数为params,它会自动传递给doInBackground(params),而不需要显式调用。
    • doInBackground()被调用的doInBackground(Progress)方法也会将Progress传递给onProgressUpdate(Progress)作为参数来更新进度。
    • doInBackground()的返回类型为Result,那么它会自动返回作为onPostExecute(Result)的参数传入。
  3. 总结起来,AsyncTask大概执行流程如下;

  • 调用AsyncTask的execute()方法
  • 执行onPreExecute()进行一些设置操作,比如进度条设置。
  • 执行doInBackground(),在新进程中进行一些耗时操作,同时通过doInBackground()来通知进度信息。
  • onProgressUpdate()响应更新进度信息,进行进度条设置。
  • 当后台任务执行完之后,onPostExecute()接收doInBackground()的结果,显示最终处理结果,并解除进度条。


完整过程示例:

使用AsyncTask下载网页并显示到页面上

 
 
public class AsyncTaskTest extends Activity
{
private TextView show;
 
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.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>
{
// 可变长的输入参数,与AsyncTask.exucute()对应
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();
// 打开conn连接对应的输入流,并将它包装成BufferedReader
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);
}
return sb.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
 
@Override
protected void onPostExecute(String result)
{
// 返回HTML页面的内容
show.setText(result);
pdialog.dismiss();
}
 
@Override
protected void onPreExecute()
{
pdialog = new ProgressDialog(mContext);
// 设置对话框的标题
pdialog.setTitle("任务正在执行中");
// 设置对话框 显示的内容
pdialog.setMessage("任务正在执行中,敬请等待...");
// 设置对话框不能用“取消”按钮关闭
pdialog.setCancelable(false);
// 设置该进度条的最大进度值
pdialog.setMax(202);
// 设置对话框的进度条风格
pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// 设置对话框的进度条是否显示进度
pdialog.setIndeterminate(false);
pdialog.show();
}
 
@Override
protected void onProgressUpdate(Integer... values)
{
// 更新进度
show.setText("已经读取了【 " + values[0] + " 】行!");
pdialog.setProgress(values[0]);
}
}
}

关于进度条的百分比计算问题:

  • ProgressDialog .setMax():设置最大进度值
  • ProgressDialog. setProgress():设置当前进度值
    系统会自动计算百分比显示出来,在的使用前要计算出最大进度值,这需要根据具体使用情况来处理。



另外一个示例:
PullToRefresh中通过AsyncTask来更新ListView的信息

 
 
import com.markupartist.android.widget.PullToRefreshListView;
import com.markupartist.android.widget.PullToRefreshListView.OnRefreshListener;
 
public class PullToRefreshActivity extends ListActivity {
private LinkedList<String> mListItems;
 
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pull_to_refresh);
 
// Set a listener to be invoked when the list should be refreshed.
((PullToRefreshListView) getListView()).setOnRefreshListener(new OnRefreshListener() {
@Override
public void onRefresh() {
// Do work to refresh the list here.
new GetDataTask().execute();
}
});
 
mListItems = new LinkedList<String>();
mListItems.addAll(Arrays.asList(mStrings));
 
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, mListItems);
 
setListAdapter(adapter);
}
 
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
 
@Override
protected String[] doInBackground(Void... params) {
// Simulates a background job.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {;}
return mStrings;
}
 
@Override
protected void onPostExecute(String[] result) {
mListItems.addFirst("Added after refresh...");
 
// Call onRefreshComplete when the list has been refreshed.
((PullToRefreshListView) getListView()).onRefreshComplete();
 
super.onPostExecute(result);
}
}
 
private String[] mStrings = {
"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam",
"Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis",
"Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
"Allgauer Emmentaler"};
}
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值