android異步操作
為了使UI在數據獲取時不僵死,數據獲取需要在新開Worker線程中進行,然後將返回結果在UI線程中進行讀取並渲染頁麵。麵對這種異步處理,到底如何寫才簡潔,先後麵臨過三種實現方式。
首先是最原始的Java方式,new 一個Thread出來,將處理Runnable進去執行,執行完之後通過handler post到ui線程去更新界麵。然後發現1.5後有了AsyncTask,非常好用,以後的項目中全部改成衍生出一個AsyncTask的子類,類中自然定義了運行前方法、運行中方法和運行後在ui中運行的方法。目前我做的項目中對AsyncTask做了封裝,把它從原本的子類編寫的過程,改成了函數調用方式,這就是目前正使用的第三種方法。
一個Android應用中,Activity通常可以建立以上層次關係。然後,在BaseActivity中對AsyncTask進行了封裝,形成doAsync方法。方法體內創建一個新的AsyncTask並執行,由於AsyncTask是泛型參數,doAsync方法中傳入的接口的參數也對應使用了泛型。至此,一個典型的異步調用的案例如下:
[java]
view plaincopy
- this.doAsync(new Callable<String>() {
- // 希望異步加載的數據
- public String call() throws Exception {
- String resu = NetworkTool.httpGetURL(
- "https://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引擎的實現代碼進行的修改。
附源碼:
[java]
view plaincopy
- 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;
- }
- }
[java]
view plaincopy
- 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);
- }
[java]
view plaincopy
- public interface Callback<T> {
- // ===========================================================
- // Final Fields
- // ===========================================================
- // ===========================================================
- // Methods
- // ===========================================================
- /**
- * 當加載完成後回調,加載完畢的事後處理
- */
- public void onCallback(final T pCallbackValue);
- }
[java]
view plaincopy
- public interface IProgressListener {
- // ===========================================================
- // Constants
- // ===========================================================
- // ===========================================================
- // Methods
- // ===========================================================
- /**
- * @param pProgress between 0 and 100.
- */
- public void onProgressChanged(final int pProgress);
- }
[java]
view plaincopy
- public interface IProgressListener {
- // ===========================================================
- // Constants
- // ===========================================================
- // ===========================================================
- // Methods
- // ===========================================================
- /**
- * @param pProgress between 0 and 100.
- */
- public void onProgressChanged(final int pProgress);
- }
[java]
view plaincopy
- 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);
- }
- }
最後更新:2017-04-03 12:54:24