以前文章中对网络加载数据过程都是一笔带过,在这里分析一种特殊情况:加载过程中,点击取消加载。
异步加载数据过程,有人喜欢用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); } }
数据加载过程与人机交互息息相关,如果控制不好,很可能多个线程去刷新一个界面数据,引起异常,所以要根据需求控制好每个异步加载任务。