以前文章中对网络加载数据过程都是一笔带过,在这里分析一种特殊情况:加载过程中,点击取消加载。
异步加载数据过程,有人喜欢用AsyncTask,有人喜欢自己控制线程池来管理加载任务队列,其实质是一样的都是实现了异步加载。
加载网络数据我大体分为两类:
1、数据加载完,刷新页面,一般用到等待框,比如新闻列表信息请求。
2、数据加载任务后台进行,不影响正常操作,比如,日志请求、数据已读请求等。
那么第一类就存在一种情况,在加载过程中,用户不想等待了,点击返回取消等待框。等待框取消证明用户放弃该页面加载,即要取消加载线程。
我们以实用AsyncTask来看以上功能的实现,直接上核心代码:
public abstract class IsAsyncTask<Params, Progress, Result> extends
AsyncTask<Params, Progress, Result> {
/**
* 加载进度条
*/
private DialogLoading dialog_loading = null;
protected String exception;
protected Activity activity;
/**
* 是否显示加载进度条 为了下拉和上拉刷新不显示加载进度条
*/
private boolean isShow = true;
public IsAsyncTask(Activity activity) {
this(activity, true, true);
}
public IsAsyncTask(Activity activity, final DialogInterface.OnCancelListener l,
boolean isShow) {
this(activity, l, true, isShow);
}
public IsAsyncTask(Activity activity, final boolean cancelable, boolean isShow) {
this(activity, null, cancelable, isShow);
}
public IsAsyncTask(Activity activity, final DialogInterface.OnCancelListener l,
final boolean cancelable, boolean isShow) {
super();
this.activity = activity;
this.isShow = isShow;
if (null == dialog_loading && isShow) {
dialog_loading = new DialogLoading(activity);
dialog_loading.setCanceledOnTouchOutside(false);
dialog_loading.setCancelable(cancelable);
dialog_loading.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
if (cancelable) {
IsAsyncTask.this.cancel(true);
}
if (l != null) {
l.onCancel(dialog);
}
}
});
}
}
@Override
protected Result doInBackground(Params... params) {
return null;
}
@Override
protected void onPostExecute(Result result) {
super.onPostExecute(result);
if (null != activity && !activity.isFinishing() && dialog_loading != null) {
dialog_loading.dismiss();
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
if (null != activity && !activity.isFinishing() && dialog_loading != null && isShow) {
dialog_loading.show();
}
}
}
过程分析:
1、创建这个异步任务的时候,就要把是否显示等待框isShow、是否允许取消cancelable。
2、当需要显示等待框时候,创建、显示并且绑定一个取消监听,当等待框取消掉时候,也取消对应的异步加载任务。
通过这样简单的把dialog和asynctask的绑定在一起,可以实现两种异步任务的加载,还可以实现等待框和加载任务的取消。
怎么使用呢,来个例子:
首先实现asynctask
private class GetPageHtmlDataTask extends
IshuguiAsyncTask<String, Void, BSPageHtmlResBeanInfo> {
private WebView webView;
public GetPageHtmlDataTask(Activity activity, WebView webView) {
super(activity, null, true);
this.webView = webView;
}
@Override
protected BSPageHtmlResBeanInfo doInBackground(String... params) {
BSPageHtmlResBeanInfo bsBeanInfo = null;
try {
bsBeanInfo = IshuguiLib.getInstance(activity).getBSPageHtmlBeanInfo(params[0],
params[1], params[2], params[3], params[4], params[5]);
} catch (HttpRequestException e) {
exception = e.getMessage();
e.printStackTrace();
} catch (JSONException e) {
exception = e.getMessage();
e.printStackTrace();
}
return bsBeanInfo;
}
@Override
protected void onPostExecute(BSPageHtmlResBeanInfo result) {
if (exception != null) {
LogUtil.d(TAG, exception);
exception = null;
ToastAlone.showToast(activity, R.string.net_work_notcool, Toast.LENGTH_LONG);
super.onPostExecute(result);
return;
}
if (result != null) {
if ("0".equals(result.getPublicBean().getStatus())) {
result.insertJsAndCssMethod(activity);
setWebView(webView, result);
} else {
ToastAlone.showToast(activity, R.string.request_data_failed,
Toast.LENGTH_SHORT);
}
} else {
ToastAlone.showToast(activity, R.string.request_data_failed,
Toast.LENGTH_SHORT);
}
super.onPostExecute(result);
}
}
getBSPageHtmlBeanInfo数据获取协议时通过httpclient实现的,这个大家应该比较熟悉了。
这样直接调用就可以了:
if (NetworkUtils.checkNet(this)) {
if (getBSPageHtmlDataTask != null) {
getBSPageHtmlDataTask.cancel(true);
}
getBSPageHtmlDataTask = new GetBSPageHtmlDataTask(this, webVi_specialTopic);
getBSPageHtmlDataTask.execute(bsType, strId, "", "", "", clientAgent);
}
还有一种加载过程是跟activity一起消亡的话:
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (getBSPageHtmlDataTask != null) {
getBSPageHtmlDataTask.cancel(true);
}
}
数据加载过程与人机交互息息相关,如果控制不好,很可能多个线程去刷新一个界面数据,引起异常,所以要根据需求控制好每个异步加载任务。