Compensating for the shortcomings of AsyncTask with BetterAsyncTask (Droid-Fu)

712 Views Asked by At

After a lengthy and unsuccessful search on google, it turns out that there is hardly any information about a handy library called Droid-Fu https://github.com/kaeppler/droid-fu

After reading the introduction by the creator (http://brainflush.wordpress.com/2009/11/16/introducing-droid-fu-for-android-betteractivity-betterservice-and-betterasynctask/) or the API (http://kaeppler.github.com/droid-fu), I could not figure out how to define a new betterasynctask (what methods hold what information etc).

So if there is anyone out there that could provide me (and apperently others as well) with some useful source code or tutorials, I would greatly appreciate it!

(If you need the jar file of the project, let me know, I can send you a copy)

EDIT:

A good example can be found here! and here

Ok, here is some additional information I found in the source code:

  1. A progress dialog is automatically shown. See useCustomDialog(), disableDialog()
  2. If an Exception is thrown from inside doInBackground, this is now handled by the handleError method.
  3. You should now longer override onPreExecute(), doInBackground() and onPostExecute(), instead you should use before(), doCheckedInBackground() and after() respectively.

Let's see what I can achieve from here on then...still looking for a working example though!

EDIT 2:

A couple of examples can be found here and here. I stick to it but I get an error. Only difference is that my AsyncTask is not defined within the activity, but a class of its own. Stepping through the code reveals that the error happens upon creation of the (AsyncTask built-in) Dialog.

This is my stacktrace:

coming in a minute

2

There are 2 best solutions below

4
On

Droid-fu is a little outdated now, mainly due to the lack of Fragment support. But I'll give an example from an app I wrote that used it.

First, your activity class has to subclass BetterActivity (or BetterXXXActivity). In my code I was using a ListActivity so mine here subclasses BetterListActivity. I also define a subclass of BetterAsyncTask so I can extend some functionality.

public class DroidFuExample extends BetterListActivity {

    private ExampleTask mTask;
    private List<Stuff> mMainStuff;

    private class ExampleTask extends BetterAsyncTask<Void, Void, Integer> {
        private List<Stuff> mStuff;
        private DroidFuExample mContext; // a context for lifecycle management
        ...
    }
}

Now, my task needs doesn't take a parameter, uses an indeterminate dialog so no progress is published, and needs to return an Integer. Your needs may differ, and that affects the types used in the class definition.

Next step is to define what the task processes in the background. In my case I need to populate mStuff. In your task class, define either doInBackground() or doCheckedInBackground() (doChecked... can throw an exception if you want to catch it).

    protected Integer doCheckedInBackground(Context context, Void... params)
            throws Exception {
        mStuff = // some long-running code (no longer on the UI thread)
        return 1;
    }

Finally, at the very least you need to do something with your result, like update a class variable or populate the UI or something. This is done in after:

    protected void after(Context context, Integer integer) {
        if (integer >= someAcceptablePositiveConstant) {
            mMainStuff = mStuff;
            doSomethingInTheUIWithMainStuff();
        } else {
            //gah!
        }
    }

As you mentioned there's more you can do with the class, such as define a before() override that does work on the UI thread before the task, or failed() / handleError() to handle unchecked/checked failures. This is just a simple example, hope it helps.

0
On

What a pain in the @ss! The error was well hidden inside the BetterActivityHelper class:

public static ProgressDialog createProgressDialog(final Activity activity,
        int progressDialogTitleId, int progressDialogMsgId) {
    ProgressDialog progressDialog = new ProgressDialog(activity);
    if (progressDialogTitleId <= 0) {
        progressDialogTitleId = activity.getResources().getIdentifier(
                PROGRESS_DIALOG_TITLE_RESOURCE, "string", activity.getPackageName());
    }
    progressDialog.setTitle(progressDialogTitleId);
    if (progressDialogMsgId <= 0) {
        progressDialogMsgId = activity.getResources().getIdentifier(
                PROGRESS_DIALOG_MESSAGE_RESOURCE, "string", activity.getPackageName());
    }
    progressDialog.setMessage(activity.getString(progressDialogMsgId));
    progressDialog.setIndeterminate(true);
    progressDialog.setOnKeyListener(new OnKeyListener() {
        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
            activity.onKeyDown(keyCode, event);
            return false;
        }
    });

progressDialogTitleId and progressDialogMsgId expect a value inside the res/values/string.xml :

<!-- Droid-Fu Progressdialog -->
<string name="droidfu_progress_dialog_title">Some nasty dialog title</string>
<string name="droidfu_progress_dialog_message">Some funny message</string>

If they are not defined, a runtime exception will be thrown.

Unfortunately, even the best helper classes are almost useless if they are UNDOCUMENTED. Took me a couple of hours to figure out what went wrong. So again, NO "Thank you" to the developer. Sor