4

这是一个我不知道该怎么做。基本上,我有一个 ASyncTask 类,它在后台照常工作。我想在它完成后做点什么。现在,在您继续说“只使用 onPostExecute()”之前,有一个问题。我需要运行的方法是在活动中,而不是在任务类中。

在我看来,我有两个选择。

A:

    CustomTask task = new CustomTask();
    task.execute(passedParams);
            //when(task.execute is finished)
            {
                doX();
            }

我希望我可以这样做,因为它是如此简单,让我检查任务何时完成,而不必不断地轮询它的活动和活动的 getStatus()。我不认为我会这么幸运,但如果有人有办法做到这一点,那就太好了

乙:

将活动作为参数传递给 ASyncTask。这很混乱,我对使用它不满意,但除此之外和对象引用,我不知道它是否会起作用

    CustomTask task = new CustomTask();
    task.execute(passedParams,MyActivity);

然后在 PostExecute 任务中,我可以让它调用 MyActivity.doX();


C:

第三种方法是使 asynctask 成为活动本身的私有类,但我真的想将它分开。可重用性和其他 -</p>

对此有什么想法吗?

综上所述,task.execute 完成后需要 doX() 。任何想法表示赞赏。


丁:

好的,我知道我在这里很顺利。我一直在想新的解决方案。可以从任何地方调用的类方法或静态方法。

public class ProfileSettings extends Activity
{
      public static void doX()
      {
          //Logic...
      }
}

从异步任务

MyActivity.doX();
4

4 回答 4

6

选项 B 应该可以工作,有时是一个不错的选择,但有时我会为此使用匿名类。当您从活动中调用它时:

CustomTask task = new CustomTask() {
    @Override
    protected void onPostExecute(Long result) {
        super.onPostExecute(result);
        MyActivity.this.doX();
    }
}.execute();
于 2012-04-11T23:20:19.620 回答
3

选项 A:

Android API 已经为此提供了内置函数AsyncTask.get()

CustomTask task = new CustomTask();
task.execute(passedParams);
Result result = task.get(); // <- Block UI thread and waiting for AsyncTask finish.
this.doX(result);

如您所见,这是一种不好的做法,因为它阻塞了 UI 线程并可能导致 ANR 异常,这样做实际上是牺牲了 AsyncTask 的好处,并使其与 UI 线程同步运行。


选项 B 和 C

两者都是正确的做事方式,通过在 onPostExecute() 方法中调用 doX() 方法,

AsyncTask,顾名思义,就是与 UI 线程异步运行一个后台线程,一旦后台线程结束,就会在 UI 线程上调用 onPostExecute 方法。在项目构建时无法准确判断 onPostExecute 方法何时被调用(即 doInBackground 方法何时完成),因为它是在应用程序运行时确定的,我们唯一知道的是 onPostExecute 方法保证在 UI 线程上被调用在未来的某个时刻,换句话说,当在项目构建时编写代码时,我们永远无法确切知道 doInBackground 何时完成并且代码执行会跳回到 onPostExecute 方法之外的 UI 线程(除非您在代码中实现一些等待机制,例如 Option一个)。所以 onPostExecute 方法的目的是处理 doInBackground 方法完成后的所有内容,

选项 B 和 C 的区别在于 AsyncTask 是作为内部类还是单独的类来实现。这已在 StackOverflow 中被多次询问和讨论。大多数人认为出于可重用性等原因将它们分开是好的。从我的角度来看,我不同意。Java 编程语言有它的理由提供内部类语法来适应一些特殊的编码情况,当从 OOP 角度谈论代码重构时,更多地从问题抽象层面思考,而不是简单地在代码层面从 Activity 类中剥离内部类。正如您在示例中看到的那样,通过将 AsyncTask 从 Activity 中分离出来,您不会获得任何真正的好处,而是会增加代码复杂性(需要在类之间传递 Activity 上下文引用)来解决问题。

我认为您真正的问题是我们是否应该将 AsyncTask 内部类实现与 Activity 隔离。为了更好地重构 OOP 代码(可重用性、可测试性等),请查看我在此StackOverflow 问题中的答案,了解如何正确地将业务层与应用程序 UI 层隔离开来。

于 2012-04-12T00:33:05.597 回答
1

我能够使用接口实现此功能:

http://howcanisolve.com/38646/android-java-equivalent-of-ios-block-callbacks

public interface ICallbacks { 
public void onResponse(JSONObject response);
public void onError(VolleyError error);
}

然后在您的例程代码中放置一个新的回调实例:

public static void getPassagesForFirebaseUser(FirebaseUser user,
Context context, ICallbacks events) { 
  //here code and call ICallbacks methods
  if(result){ events.onResponse(response); }
  if(error){ events.onError(err); }
}

最终您可以使用以下方法调用该方法:

getPassagesForFirebaseUser(user, context, new ICallbacks(){
  @Override
  public void onResponse(JSONObject response){
      //Success !!!
  }
  @Override
  public void onError(VolleyError response){
      //Error !!!
  }
});
于 2017-02-27T17:15:01.833 回答
0

选项 B 通常更安全。但即便如此,你也需要小心。您需要将您的(不仅仅是类)的实例存储在. 如果在任务运行时被销毁(如果用户按下后退按钮怎么办?),您需要将此通知任务,以便任务不会尝试调用 dead 上的方法。ActivityASyncTaskActivityActivity

如果Activity它恢复生机(例如,在屏幕旋转之后),那么您需要将新Activity的重新附加到正在运行的任务中。

这些东西很繁琐。

于 2012-04-11T23:15:51.983 回答