Android Open Source - droid-fu Better Async Task






From Project

Back to project page droid-fu.

License

The source code is released under:

Apache License

If you think the Android project droid-fu listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/* Copyright (c) 2009 Matthias Kppler
 *//from w  ww  .  j  av a 2  s .  c o m
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.droidfu.concurrent;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.Window;

import com.github.droidfu.DroidFuApplication;
import com.github.droidfu.activities.BetterActivity;

/**
 * Works in a similar way to AsyncTask but provides extra functionality.
 *
 * 1) It keeps track of the active instance of each Context, ensuring that the
 * correct instance is reported to. This is very useful if your Activity is
 * forced into the background, or the user rotates his device.
 *
 * 2) A progress dialog is automatically shown. See useCustomDialog()
 * disableDialog()
 *
 * 3) If an Exception is thrown from inside doInBackground, this is now handled
 * by the handleError method.
 *
 * 4) You should now longer override onPreExecute(), doInBackground() and
 * onPostExecute(), instead you should use before(), doCheckedInBackground() and
 * after() respectively.
 *
 * These features require that the Application extends DroidFuApplication.
 *
 * @param <ParameterT>
 * @param <ProgressT>
 * @param <ReturnT>
 */
public abstract class BetterAsyncTask<ParameterT, ProgressT, ReturnT> extends
        AsyncTask<ParameterT, ProgressT, ReturnT> {

    private final DroidFuApplication appContext;
    private final boolean contextIsDroidFuActivity;

    private Exception error;

    private boolean isTitleProgressEnabled,
            isTitleProgressIndeterminateEnabled = true;

    private final String callerId;

    private BetterAsyncTaskCallable<ParameterT, ProgressT, ReturnT> callable;

    private int dialogId = 0;

    /**
     * Creates a new BetterAsyncTask who displays a progress dialog on the specified Context.
     *
     * @param context
     */
    public BetterAsyncTask(Context context) {

        if (!(context.getApplicationContext() instanceof DroidFuApplication)) {
            throw new IllegalArgumentException(
                    "context bound to this task must be a DroidFu context (DroidFuApplication)");
        }
        this.appContext = (DroidFuApplication) context.getApplicationContext();
        this.callerId = context.getClass().getCanonicalName();
        this.contextIsDroidFuActivity = context instanceof BetterActivity;

        appContext.setActiveContext(callerId, context);

        if (contextIsDroidFuActivity) {
            int windowFeatures = ((BetterActivity) context).getWindowFeatures();
            if (Window.FEATURE_PROGRESS == (Window.FEATURE_PROGRESS & windowFeatures)) {
                this.isTitleProgressEnabled = true;
            } else if (Window.FEATURE_INDETERMINATE_PROGRESS == (Window.FEATURE_INDETERMINATE_PROGRESS & windowFeatures)) {
                this.isTitleProgressIndeterminateEnabled = true;
            }
        }
    }

    /**
     * Gets the most recent instance of this Context.
     * This may not be the Context used to construct this BetterAsyncTask as that Context might have been destroyed
     * when a incoming call was received, or the user rotated the screen.
     *
     * @return The current Context, or null if the current Context has ended, and a new one has not spawned.
     */
    protected Context getCallingContext() {
        try {
            Context caller = (Context) appContext.getActiveContext(callerId);
            if (caller == null || !this.callerId.equals(caller.getClass().getCanonicalName())
                    || (caller instanceof Activity && ((Activity) caller).isFinishing())) {
                // the context that started this task has died and/or was
                // replaced with a different one
                return null;
            }
            return caller;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    protected final void onPreExecute() {
        Context context = getCallingContext();
        if (context == null) {
            Log.d(BetterAsyncTask.class.getSimpleName(), "skipping pre-exec handler for task "
                    + hashCode() + " (context is null)");
            cancel(true);
            return;
        }

        if (contextIsDroidFuActivity) {
            Activity activity = (Activity) context;
            if (dialogId > -1) {
                activity.showDialog(dialogId);
            }
            if (isTitleProgressEnabled) {
                activity.setProgressBarVisibility(true);
            } else if (isTitleProgressIndeterminateEnabled) {
                activity.setProgressBarIndeterminateVisibility(true);
            }
        }
        before(context);
    }

    /**
     * Override to run code in the UI thread before this Task is run.
     *
     * @param context
     */
    protected void before(Context context) {
    }

    @Override
    protected final ReturnT doInBackground(ParameterT... params) {
        ReturnT result = null;
        Context context = getCallingContext();
        try {
            result = doCheckedInBackground(context, params);
        } catch (Exception e) {
            this.error = e;
        }
        return result;
    }

    /**
     * Override to perform computation in a background thread
     *
     * @param context
     * @param params
     * @return
     * @throws Exception
     */
    protected ReturnT doCheckedInBackground(Context context, ParameterT... params) throws Exception {
        if (callable != null) {
            return callable.call(this);
        }
        return null;
    }

    /**
     * Runs in the UI thread if there was an exception throw from doCheckedInBackground
     *
     * @param context The most recent instance of the Context that executed this BetterAsyncTask
     * @param error The thrown exception.
     */
    protected abstract void handleError(Context context, Exception error);

    @Override
    protected final void onPostExecute(ReturnT result) {
        Context context = getCallingContext();
        if (context == null) {
            Log.d(BetterAsyncTask.class.getSimpleName(), "skipping post-exec handler for task "
                    + hashCode() + " (context is null)");
            return;
        }

        if (contextIsDroidFuActivity) {
            Activity activity = (Activity) context;
            if (dialogId > -1) {
                activity.removeDialog(dialogId);
            }
            if (isTitleProgressEnabled) {
                activity.setProgressBarVisibility(false);
            } else if (isTitleProgressIndeterminateEnabled) {
                activity.setProgressBarIndeterminateVisibility(false);
            }
        }

        if (failed()) {
            handleError(context, error);
        } else {
            after(context, result);
        }
    }

    /**
     * A replacement for onPostExecute. Runs in the UI thread after doCheckedInBackground returns.
     *
     * @param context The most recent instance of the Context that executed this BetterAsyncTask
     * @param result The result returned from doCheckedInBackground
     */
    protected abstract void after(Context context, ReturnT result);

    /**
     * Has an exception been thrown inside doCheckedInBackground()
     * @return
     */
    public boolean failed() {
        return error != null;
    }

    /**
     * Use a BetterAsyncTaskCallable instead of overriding doCheckedInBackground()
     *
     * @param callable
     */
    public void setCallable(BetterAsyncTaskCallable<ParameterT, ProgressT, ReturnT> callable) {
        this.callable = callable;
    }

    /**
     * Use a custom resource ID for the progress dialog
     *
     * @param dialogId
     */
    public void useCustomDialog(int dialogId) {
        this.dialogId = dialogId;
    }

    /**
     * Disable the display of a dialog during the execution of this task.
     */
    public void disableDialog() {
        this.dialogId = -1;
    }
}




Java Source Code List

com.github.droidfu.DroidFuApplication.java
com.github.droidfu.DroidFu.java
com.github.droidfu.activities.BetterActivityHelper.java
com.github.droidfu.activities.BetterActivity.java
com.github.droidfu.activities.BetterDefaultActivity.java
com.github.droidfu.activities.BetterExpandableListActivity.java
com.github.droidfu.activities.BetterListActivity.java
com.github.droidfu.activities.BetterMapActivity.java
com.github.droidfu.activities.BetterPreferenceActivity.java
com.github.droidfu.adapters.ListAdapterWithProgress.java
com.github.droidfu.adapters.WebGalleryAdapter.java
com.github.droidfu.cachefu.AbstractCache.java
com.github.droidfu.cachefu.CacheHelper.java
com.github.droidfu.cachefu.CachedList.java
com.github.droidfu.cachefu.CachedModel.java
com.github.droidfu.cachefu.HttpResponseCache.java
com.github.droidfu.cachefu.ImageCache.java
com.github.droidfu.cachefu.ModelCache.java
com.github.droidfu.concurrent.BetterAsyncTaskCallable.java
com.github.droidfu.concurrent.BetterAsyncTask.java
com.github.droidfu.dialogs.DialogClickListener.java
com.github.droidfu.exception.ResourceMessageException.java
com.github.droidfu.http.BetterHttpRequestBase.java
com.github.droidfu.http.BetterHttpRequestRetryHandler.java
com.github.droidfu.http.BetterHttpRequest.java
com.github.droidfu.http.BetterHttpResponseImpl.java
com.github.droidfu.http.BetterHttpResponse.java
com.github.droidfu.http.BetterHttp.java
com.github.droidfu.http.CachedHttpRequest.java
com.github.droidfu.http.CachedHttpResponse.java
com.github.droidfu.http.ConnectionChangedBroadcastReceiver.java
com.github.droidfu.http.HttpDelete.java
com.github.droidfu.http.HttpGet.java
com.github.droidfu.http.HttpPost.java
com.github.droidfu.http.HttpPut.java
com.github.droidfu.http.ssl.EasySSLSocketFactory.java
com.github.droidfu.http.ssl.TrivialTrustManager.java
com.github.droidfu.imageloader.ImageLoaderHandler.java
com.github.droidfu.imageloader.ImageLoader.java
com.github.droidfu.listeners.MapGestureListener.java
com.github.droidfu.services.BetterService.java
com.github.droidfu.support.ArraySupport.java
com.github.droidfu.support.DiagnosticSupport.java
com.github.droidfu.support.DisplaySupport.java
com.github.droidfu.support.IntentSupport.java
com.github.droidfu.support.StringSupport.java
com.github.droidfu.testsupport.DroidFuAssertions.java
com.github.droidfu.widgets.WebImageView.java
com.google.common.base.FinalizableReferenceQueue.java
com.google.common.base.FinalizableReference.java
com.google.common.base.FinalizableSoftReference.java
com.google.common.base.FinalizableWeakReference.java
com.google.common.base.Function.java
com.google.common.base.Objects.java
com.google.common.base.internal.Finalizer.java
com.google.common.collect.AbstractMapEntry.java
com.google.common.collect.AsynchronousComputationException.java
com.google.common.collect.ComputationException.java
com.google.common.collect.CustomConcurrentHashMap.java
com.google.common.collect.ExpirationTimer.java
com.google.common.collect.MapMaker.java
com.google.common.collect.NullOutputException.java