为了使UI在数据获取时不僵死,数据获取需要在新开Worker线程中进行,然后将返回结果在UI线程中进行读取并渲染页面。面对这种异步处理,到底如何写才简洁,先后面临过三种实现方式。

首先是最原始的Java方式,new 一个Thread出来,将处理Runnable进去执行,执行完之后通过handler post到ui线程去更新界面。然后发现1.5后有了AsyncTask,非常好用,以后的项目中全部改成衍生出一个AsyncTask的子类,类中自然定义了运行前方法、运行中方法和运行后在ui中运行的方法。目前我做的项目中对AsyncTask做了封装,把它从原本的子类编写的过程,改成了函数调用方式,这就是目前正使用的第三种方法。

一个Android应用中,Activity通常可以建立以上层次关系。然后,在BaseActivity中对AsyncTask进行了封装,形成doAsync方法。方法体内创建一个新的AsyncTask并执行,由于AsyncTask是泛型参数,doAsync方法中传入的接口的参数也对应使用了泛型。至此,一个典型的异步调用的案例如下:

this.doAsync(new Callable<String>() { // 希望异步加载的数据 public String call() throws Exception { String resu = NetworkTool.httpGetURL( "http://www.baidu.com", "GBK"); return resu; } }, new Callback<String>() { // 当加载完成后回调,在UI线程中的操作 public void onCallback(final String resu) { if (null != resu) { tv_text1.setText(getRT().text1 + resu); } else { Tools.ShowNetErr(HomeActivity.this); } } });

这样,就从本来继承AsyncTask创建一个子类,然后初始化,然后运行的开发过程转变为了函数调用的过程。可以看到,调用可是简洁了很多!

为了实现它,我们附上BaseActivity中如下封装代码,需要说明的是这不是我的原创,我借鉴于Andengine引擎的实现代码进行的修改。

附源码:

public class ActivityUtils { public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback) { ActivityUtils.doAsync(pContext, pTitleResID, pMessageResID, pCallable, pCallback, null, false); } public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback) { ActivityUtils.doAsync(pContext, pTitle, pMessage, pCallable, pCallback, null, false); } public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final boolean pCancelable) { ActivityUtils.doAsync(pContext, pTitleResID, pMessageResID, pCallable, pCallback, null, pCancelable); } public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback, final boolean pCancelable) { ActivityUtils.doAsync(pContext, pTitle, pMessage, pCallable, pCallback, null, pCancelable); } public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { ActivityUtils.doAsync(pContext, pTitleResID, pMessageResID, pCallable, pCallback, pExceptionCallback, false); } public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { ActivityUtils.doAsync(pContext, pTitle, pMessage, pCallable, pCallback, pExceptionCallback, false); } public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback, final boolean pCancelable) { ActivityUtils.doAsync(pContext, pContext.getString(pTitleResID), pContext.getString(pMessageResID), pCallable, pCallback, pExceptionCallback, pCancelable); } public static <T> void doAsync(final Context pContext, final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback, final boolean pCancelable) { new AsyncTask<Void, Void, T>() { private ProgressDialog mPD; private Exception mException = null; @Override public void onPreExecute() { this.mPD = ProgressDialog.show(pContext, pTitle, pMessage, true, pCancelable); if(pCancelable) { this.mPD.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(final DialogInterface pDialogInterface) { pExceptionCallback.onCallback(new CancelledException()); pDialogInterface.dismiss(); } }); } super.onPreExecute(); } @Override public T doInBackground(final Void... params) { try { return pCallable.call(); } catch (final Exception e) { this.mException = e; } return null; } @Override public void onPostExecute(final T result) { try { this.mPD.dismiss(); } catch (final Exception e) { Log.e("Error", e.toString()); } if(this.isCancelled()) { this.mException = new CancelledException(); } if(this.mException == null) { pCallback.onCallback(result); } else { if(pExceptionCallback == null) { if (this.mException != null) Log.e("Error", this.mException.toString()); } else { pExceptionCallback.onCallback(this.mException); } } super.onPostExecute(result); } }.execute((Void[]) null); } public static <T> void doProgressAsync(final Context pContext, final int pTitleResID, final ProgressCallable<T> pCallable, final Callback<T> pCallback) { ActivityUtils.doProgressAsync(pContext, pTitleResID, pCallable, pCallback, null); } public static <T> void doProgressAsync(final Context pContext, final int pTitleResID, final ProgressCallable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { new AsyncTask<Void, Integer, T>() { private ProgressDialog mPD; private Exception mException = null; @Override public void onPreExecute() { this.mPD = new ProgressDialog(pContext); this.mPD.setTitle(pTitleResID); this.mPD.setIcon(android.R.drawable.ic_menu_save); this.mPD.setIndeterminate(false); this.mPD.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); this.mPD.show(); super.onPreExecute(); } @Override public T doInBackground(final Void... params) { try { return pCallable.call(new IProgressListener() { @Override public void onProgressChanged(final int pProgress) { onProgressUpdate(pProgress); } }); } catch (final Exception e) { this.mException = e; } return null; } @Override public void onProgressUpdate(final Integer... values) { this.mPD.setProgress(values[0]); } @Override public void onPostExecute(final T result) { try { this.mPD.dismiss(); } catch (final Exception e) { Log.e("Error", e.getLocalizedMessage()); /* Nothing. */ } if(this.isCancelled()) { this.mException = new CancelledException(); } if(this.mException == null) { pCallback.onCallback(result); } else { if(pExceptionCallback == null) { Log.e("Error", this.mException.getLocalizedMessage()); } else { pExceptionCallback.onCallback(this.mException); } } super.onPostExecute(result); } }.execute((Void[]) null); } public static <T> void doAsync(final Context pContext, final int pTitleResID, final int pMessageResID, final AsyncCallable<T> pAsyncCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { final ProgressDialog pd = ProgressDialog.show(pContext, pContext.getString(pTitleResID), pContext.getString(pMessageResID)); pAsyncCallable.call(new Callback<T>() { @Override public void onCallback(final T result) { try { pd.dismiss(); } catch (final Exception e) { Log.e("Error", e.getLocalizedMessage()); /* Nothing. */ } pCallback.onCallback(result); } }, pExceptionCallback); } public static class CancelledException extends Exception { private static final long serialVersionUID = -78123211381435595L; } }

public interface AsyncCallable<T> { // =========================================================== // Final Fields // =========================================================== // =========================================================== // Methods // =========================================================== /** * Computes a result asynchronously, return values and exceptions are to be handled through the callbacks. * This method is expected to return almost immediately, after starting a {@link Thread} or similar. * * @return computed result * @throws Exception if unable to compute a result */ public void call(final Callback<T> pCallback, final Callback<Exception> pExceptionCallback); }

public interface Callback<T> { // =========================================================== // Final Fields // =========================================================== // =========================================================== // Methods // =========================================================== /** * 当加载完成后回调,加载完毕的事后处理 */ public void onCallback(final T pCallbackValue); }

public interface IProgressListener { // =========================================================== // Constants // =========================================================== // =========================================================== // Methods // =========================================================== /** * @param pProgress between 0 and 100. */ public void onProgressChanged(final int pProgress); }

public interface IProgressListener { // =========================================================== // Constants // =========================================================== // =========================================================== // Methods // =========================================================== /** * @param pProgress between 0 and 100. */ public void onProgressChanged(final int pProgress); }

public class BaseActivity extends Activity { /** * * @param <T> 模板参数,操作时要返回的内容 * @param pCallable 需要异步调用的操作 * @param pCallback 回调 */ protected <T> void doAsync(final Callable<T> pCallable, final Callback<T> pCallback) { ActivityUtils.doAsync(this, null, "内容读取中,请稍等...", pCallable, pCallback, null, false); } protected <T> void doAsync(final CharSequence pTitle, final CharSequence pMessage, final Callable<T> pCallable, final Callback<T> pCallback) { ActivityUtils.doAsync(this, pTitle, pMessage, pCallable, pCallback, null, false); } /** * Performs a task in the background, showing a {@link ProgressDialog}, * while the {@link Callable} is being processed. * * @param <T> * @param pTitleResID * @param pMessageResID * @param pErrorMessageResID * @param pCallable * @param pCallback */ protected <T> void doAsync(final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback) { this.doAsync(pTitleResID, pMessageResID, pCallable, pCallback, null); } /** * Performs a task in the background, showing a indeterminate {@link ProgressDialog}, * while the {@link Callable} is being processed. * * @param <T> * @param pTitleResID * @param pMessageResID * @param pErrorMessageResID * @param pCallable * @param pCallback * @param pExceptionCallback */ protected <T> void doAsync(final int pTitleResID, final int pMessageResID, final Callable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { ActivityUtils.doAsync(this, pTitleResID, pMessageResID, pCallable, pCallback, pExceptionCallback); } /** * Performs a task in the background, showing a {@link ProgressDialog} with an ProgressBar, * while the {@link AsyncCallable} is being processed. * * @param <T> * @param pTitleResID * @param pMessageResID * @param pErrorMessageResID * @param pAsyncCallable * @param pCallback */ protected <T> void doProgressAsync(final int pTitleResID, final ProgressCallable<T> pCallable, final Callback<T> pCallback) { this.doProgressAsync(pTitleResID, pCallable, pCallback, null); } /** * Performs a task in the background, showing a {@link ProgressDialog} with a ProgressBar, * while the {@link AsyncCallable} is being processed. * * @param <T> * @param pTitleResID * @param pMessageResID * @param pErrorMessageResID * @param pAsyncCallable * @param pCallback * @param pExceptionCallback */ protected <T> void doProgressAsync(final int pTitleResID, final ProgressCallable<T> pCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { ActivityUtils.doProgressAsync(this, pTitleResID, pCallable, pCallback, pExceptionCallback); } /** * Performs a task in the background, showing an indeterminate {@link ProgressDialog}, * while the {@link AsyncCallable} is being processed. * * @param <T> * @param pTitleResID * @param pMessageResID * @param pErrorMessageResID * @param pAsyncCallable * @param pCallback * @param pExceptionCallback */ protected <T> void doAsync(final int pTitleResID, final int pMessageResID, final AsyncCallable<T> pAsyncCallable, final Callback<T> pCallback, final Callback<Exception> pExceptionCallback) { ActivityUtils.doAsync(this, pTitleResID, pMessageResID, pAsyncCallable, pCallback, pExceptionCallback); } }

更多相关文章

  1. SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
  2. Android(安卓)反射调用方法并利用此方法展开android通知栏(兼容4.
  3. 这可能是最好的 Android/Kotlin日志输出方法
  4. 【SMS】android 短信接收流程分析——-拦截短信示例代码
  5. Android(安卓)四种线程池
  6. 这一年半以来,关于 Android,我都写了些什么?(一)
  7. android线程 Handler Message Queue AsyncTask线程模型 线程交互
  8. 10个提高Android(安卓)App性能的建议
  9. Android学习路线(十四)Activity生命周期——停止和重启(Stopping a

随机推荐

  1. Android主流三方库源码分析(七、深入理解B
  2. 从Alarm看Android上层UI到内核代码的流程
  3. Android的IPC机制Binder的各个部分
  4. Android-ListView几个比较特别的属性
  5. Android Project Structure
  6. 【android】欢迎来到Android多进程时代
  7. Android兼容性测试框架(CTS)手册
  8. 让低版本的 Android(安卓)项目显示出 Mat
  9. 从源码角度一步步分析AsyncTask的用法与
  10. [转】:Android生命周期