【问题标题】:Why am I getting this ClassCastException in my AsyncTask?为什么我的 AsyncTask 中会出现这个 ClassCastException?
【发布时间】:2026-01-28 17:55:02
【问题描述】:

首先,请不要 tl;dr 这个。它只是很多可快速扫描的代码。实际的句子少而简洁:)。

我有一个奇怪的问题。 ClassCastException 正在强制关闭我的 Activity,但该异常并未表明问题实际出在哪里。这是一个例外:

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

如您所见,它表示错误发生在DayActivity.java 的第 1 行,这是默认的包声明(即package mypackage)。

这是我的doInBackground 方法。在这里,怪异加剧了,因为整个方法基本上是一个try/catch 块:

@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;
}

理论上,任何抛出的异常都应该被捕获并记录下来。我不明白这怎么可能发生。诀窍是在onPostExecute,我运行这段代码:

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

这里是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();
}

问题是任务运行一次,对话框显示出来,但是当我点击重试时抛出异常,导致我的应用程序崩溃。

【问题讨论】:

    标签: java android android-asynctask classcastexception


    【解决方案1】:

    你要传入什么AsyncTask 来重试?一个AsyncTask 只能执行一次,所以你需要创建一个新的实例,而不是尝试重启已经执行的实例。取自javadoc for AsyncTask

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

    编辑:..这就是我解释堆栈跟踪的方式。在 AsyncTask 中执行 done 时出现问题。错误的地方是Object[] 的演员阵容并非如此。可能从doInBackgroundonPostExecute 时,但这只是一个疯狂的猜测。可能是由任务重新启动引起的,如果您正在尝试这样做的话。

    【讨论】:

    • 我的EventsFetcher 正在扩展AsyncTask&lt;Void, Void, List&lt;Event&gt;&gt; 并且在尝试将doInBackground 的结果转换为Object 或类似的东西时确实抛出了该异常。我刚刚将retryDialog 的第四个参数更改为AsyncTask&lt;Void, Void, List&lt;Event&gt;&gt; 并且它起作用了。
    • 谢谢,它也帮助解决了我的问题。我声明了一个新的 AsyncTask() 并且由于未知原因,我得到了与 OP 相同的异常。当我把它改成AsyncTask(),只从doInBackground()返回"",错误就消失了。
    【解决方案2】:
    if (!connectivityReceiver.hasConnection()) {
    Util.retryDialog(DayActivity.this, R.string.no_cache, R.string.no_cache_msg,
        new EventsFetcher(dialog), false).show();
    

    }

    这里是看到new EventsFetcher(dialog)被映射到final AsyncTask retry是这个原因吗?

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

    【讨论】:

    • EventsFetcher 类扩展了AsyncTask&lt;Void, Void, Void&gt;。它与包含已发布的doInBackground 和来自onPostExecute 的部分相同的类。它基本上是一个 AsyncTask 重试自身
    • @Felix 你看到我的帖子了吗?你不能执行AsyncTask 两次
    • @Kaj 是的,这就是它创建EventsFetcher 的新实例的原因(我正在传递new EventsFetcher(dialog))。
    • @Felix。你的 onPostExecute 方法是什么样的?
    【解决方案3】:

    刚刚遇到同样的问题。解决方案不是公认的答案,而是下面的 felix 评论: 确保您的 AsyncTask 引用是类型安全的。含义:使用AsyncTask&lt;Your, Parameter, Types&gt; 而不仅仅是AsyncTask。后者似乎默认为AsyncTask&lt;Object, Object, Object&gt;,因此来自Object的ClassCastException

    【讨论】:

      最近更新 更多