简体   繁体   中英

Why am I getting this ClassCastException in my AsyncTask?

First off, please do not tl;dr this. It just a lot of quickly-scannable code. Actual sentences are few and concise :).

I have a weird problem. A ClassCastException is force-closing my Activity , but the exception does not indicate where the problem actually is. Here's the exception:

E/AndroidRuntime(  402): FATAL EXCEPTION: AsyncTask #4
E/AndroidRuntime(  402): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(  402):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
E/AndroidRuntime(  402):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
E/AndroidRuntime(  402):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
E/AndroidRuntime(  402):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
E/AndroidRuntime(  402):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
E/AndroidRuntime(  402):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
E/AndroidRuntime(  402):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
E/AndroidRuntime(  402):    at java.lang.Thread.run(Thread.java:1019)
E/AndroidRuntime(  402): Caused by: java.lang.ClassCastException: [Ljava.lang.Object;
E/AndroidRuntime(  402):    at mypackage.DayActivity$EventsFetcher.doInBackground(DayActivity.java:1)
E/AndroidRuntime(  402):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
E/AndroidRuntime(  402):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
E/AndroidRuntime(  402):    ... 4 more
W/ActivityManager(   61):   Force finishing activity mypackage/mypackage.DayActivity

As you can see, it says that the error occurs on line 1 of DayActivity.java , which is the default package declaration (ie package mypackage ).

Here's my doInBackground method. Here, the weirdness intensifies, as the whole method is basically a try/catch block:

@Override
protected List<Event> doInBackground(Void... params) {
    try {
        final List<Event> events;
        if (connectivityReceiver.hasConnection()) {
            events = WebApi.getEvents(Util.getSelectedUser(DayActivity.this).getId(), start, end);
        }
        else if (Util.isPeriodCached(DayActivity.this, start, end)) {
            final List<Event> allEvents = (List<Event>) new Cache(DayActivity.this).get(Cache.EVENTS);
            events = Util.filterEvents(allEvents, start, end, Util.getSelectedUser(DayActivity.this).getId());
        }
        else {
            events = null;
        }
        return events;
    }
    catch (Exception e) {
        Log.e(Const.TAG, "Could not fetch events for day view", e);
    }
    return null;
}

In theory, any exception thrown should be caught and logged. I don't see how that could not happen. The trick is that in onPostExecute , I run this code:

if (!connectivityReceiver.hasConnection()) {
    Util.retryDialog(DayActivity.this, R.string.no_cache, R.string.no_cache_msg,
        new EventsFetcher(dialog), false).show();
}

Here's retryDialog() :

public static Dialog retryDialog(final Activity context, int titleRes, int messageRes,
        final AsyncTask retry, final boolean finishOnCancel) {
    return new AlertDialog.Builder(context)
        .setTitle(titleRes)
        .setMessage(messageRes)
        .setPositiveButton(R.string.retry, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (retry != null) {
                    retry.execute();
                }
            }
        })
        .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (finishOnCancel) {
                    context.finish();
                }
            }
        })
        .create();
}

The problem is that the task works once, the dialog gets displayed, but then when I click retry that exception is thrown, crashing my app.

What AsyncTask are you passing in to retry? an AsyncTask can only execute once, so you need to create a new instance, and not try to restart the already executed instance. Taken from the javadoc for AsyncTask :

The task can be executed only once (an exception will be thrown if a second execution is attempted.)

Edit: .. this is how I interpret the stacktrace. Something is going wrong when executing done in AsyncTask. The thing that is wrong is a cast of Object[] to something that it isn't. Possibly when going from doInBackground to onPostExecute , but that's just a wild guess. Might be caused by a restart of the task, if that is what you are trying to do.

Just had the same problem. The Solution is not the accepted answer but rather felix comment below it: Make sure your AsyncTask reference is typesafe. Meaning: use AsyncTask<Your, Parameter, Types> instead of just AsyncTask . Latter seems to default to AsyncTask<Object, Object, Object> and therefore the ClassCastException from Object

if (!connectivityReceiver.hasConnection()) {
Util.retryDialog(DayActivity.this, R.string.no_cache, R.string.no_cache_msg,
    new EventsFetcher(dialog), false).show();

}

Here is see new EventsFetcher(dialog) is mapped to final AsyncTask retry is this the cause?

public static Dialog retryDialog(final Activity context, int titleRes, int messageRes,
    final AsyncTask retry, final boolean finishOnCancel) {

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM