AsyncTask的onPostExecute方法从未被调用

40

我不确定自己做错了什么,但是onPostExecute从未被调用。

  • 创建了一个名为BaseActivity.java的基类。
  • 在原始Activity中扩展了这个类。
  • 将PostToOpenFeint类放置在BaseActivity中。
  • 通过从主Activity的UI线程调用它来执行:

  • new PostToOpenFeint.execute();
    

执行onPreExecute()和doInBackground(..),但由于某种原因,onPostExecute从未被调用。

提前感谢您!

Dave

 private class PostToOpenFeint extends AsyncTask<Void, Void, Void> {
  /*
   * (non-Javadoc)
   * 
   * @see android.os.AsyncTask#doInBackground(Params[])
   */
  @Override
  protected Void doInBackground(Void... params) {
   // does all the work here
   return null;
  }


  /*
   * (non-Javadoc)
   * 
   * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
   */
  @Override
  protected void onPostExecute(Void result) {
   // TODO Auto-generated method stub
   super.onPostExecute(result);
   Toast.makeText(MainScreen.this, "Done syncing", Toast.LENGTH_LONG).show();
  }

  /*
   * (non-Javadoc)
   * 
   * @see android.os.AsyncTask#onPreExecute()
   */
  @Override
  protected void onPreExecute() {
   // TODO Auto-generated method stub
   super.onPreExecute();
   Toast.makeText(MainScreen.this, "About to sync all your scores", Toast.LENGTH_LONG).show();
  }

我进一步研究了一下,这是我观察到的情况。例如,如果我进行以下调用:

 new PostToOpenFeint.execute();

如果我在Activity的onCreate方法之后立即调用它,那么一切正常。但是,如果我将这个调用放到按钮监听器中,就会出现问题。

settingsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
   new PostToOpenFeint.execute();
}
});

onPostExecute()从未被调用,不确定我做错了什么。我读到的限制是从UI线程调用它,而我正在从UI线程调用它。


请修正您的帖子标题:应将ActiveTask替换为AsyncTask。 - Kevin Gaudin
啊,谢谢,看起来好像有人比我先完成了。 - ddavtian
你解决过这个问题吗?我现在也遇到了同样的问题。当从一个按钮的 onClickListener 中调用时行为相同。 - Bashorings
2
算了,我不应该直接调用doInBackground()方法而不是像我对待其他任务一样调用execute()方法...我也不知道怎么会这样。:-P - Bashorings
@Bashorings,直接调用doInBackground并不是一个好主意,这样做会破坏异步任务的目的,因为它会在UI线程中同步调用所有方法。 - kiwijus
11个回答

73

我刚刚也遇到了类似的问题。我正在扩展AsyncTask<Integer,Integer,Integer>,我的onPostExecute方法如下:

protected void onPostExecute(int result)

我认为这样做没问题,但毕竟我更擅长.NET而不是Java。 我将它改为:

protected void onPostExecute(Integer result)

因为某些原因,Java认为intInteger之间存在差异?

我认为你的问题在于你在以下代码中将返回类型声明为void

extends<Void,Void,Void>

这意味着没有参数,没有进度和没有结果。如果你想在完成时执行某些操作,我认为你需要给它一些值,比如整数或布尔值。

如果你将扩展改为:

<Void,Void,Integer>

现在你没有传递任何参数,也没有发布任何进度,但是返回了一个值。请将您的onPostExecute方法更改为接受一个Integer

protected void onPostExecute(Integer result)

然后在您的doInBackground方法中将返回值更改为以下内容:

return 1;

那么它应该为您执行。


11
+1表示:“Java认为int和Integer之间有区别”。 - Zonata
20
int和Integer有区别。Int是基本数据类型,不能为null;而Integer是对象,可以为null。在调用返回Integer的函数时,如果你尝试将其存储到int中并且遇到空指针异常,则这一点尤其重要。 - f20k
3
提供一个提示或建议:你可以通过在重写的方法上标记@Override注解,利用编译器来检测此类问题。对于onPostExecute(int result)方法,它会显示一个错误,指示没有具有int参数的超级方法。 顺便说一下,Void结果值同样适用。 - Michael Jess
同样在 Xamarin 中,如果您想传递自定义对象或 C# 对象,请确保将这些对象扩展到 Java.Lang.Object - Pierre

13

关于AsyncTasks还有一个值得注意的问题,我刚刚花了半天时间才搞清楚:

AsyncTask类必须在UI线程上加载。自JELLY_BEAN版本以来这已经被自动处理了。

文档如此说明。但在Gingerbread(以及可能之前的版本)中,如果遇到特定情况,这会导致onPostExecute方法不被执行。但是解决方案很简单,只需

new MyAsyncTask();

为了避免后台进程中的任何意外加载,应该尽早在UI线程中加载该类。

我曾经在AsyncTask子类中的后台线程中使用静态函数,具体取决于时间,它可能会在UI线程中的任何内容使用AsyncTask子类之前被调用,这就是一个很好的Heisenbug。

请容忍我回答这个旧问题,因为我没有在任何地方找到那个详细的信息,而且这是我的第一篇帖子。


谢谢你提到UI线程。在我的情况下,它帮助我找到了协程调度器中的错误。 - CoolMind

9
请注意,如果您通过cancel() 取消任务, 那么onPostExecute()将不会被调用。这很合乎逻辑,但是简单地忽略了对该方法的调用使我感到困惑。

7

我的问题是我没有正确地 @Override onPostExecute 方法。我通过点击鼠标右键 -> source -> Override\Implement method 来解决这个问题。

希望对某些人有所帮助。


2

也许doInBackground()中的代码永远不会返回?


2
我遇到了这个问题,我百分之百确定在doInBackground()调用结束时返回了一个有效的Bitmap,但它在GL线程中,这是否有任何影响? - HaMMeReD

1

将以下代码添加到您的Activity中。这是Async Task没有按照预期正确初始化的问题。

          try {
                Class.forName("android.os.AsyncTask");
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

1

只需返回一个值而不是 null,就可以正常工作!
例如:
return "完成";


1

只需在onPostExecute中更改参数。

@Override
protected void onPostExecute(Void unused) {
...}

现在应该调用该方法。

0

只需在onPostExecute中使用正确的参数,使用 public void onPostExecute(Boolean response) { } 而不是 public void onPostExecute(boolean response) { } 这解决了我的问题


我认为它不应该是 public void onPostExecute,而应该是 protected void onPostExecute - kAmol

0

我也遇到了同样的问题, 我犯了一个错误,就是试图在不同的作用域中编写该方法。 只有当您在doInBackground方法后面并且在PostToOpenFeint类内部编写该方法时,该方法才会触发(在这种情况下)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接