在ASyncTask.execute()之后从Activity执行x()

这是一个我不知道如何去做的。 基本上我有一个ASyncTask类,它在后台照常开展业务。 完成后我想做些什么。 现在,在你跳到前面说“只使用onPostExecute()”之前,这是一个问题。 我需要运行的方法是在activity而不是Task类。

我看到它的方式,我有两个选择。

A:

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

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

B:

将活动作为参数传递给ASyncTask。 这很麻烦,我不喜欢使用它,但除了那个和对象参考,我不知道它是否会工作

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

然后在Tasks onPostExecute中,我可以让它调用MyActivity.doX();


C:

第三种方法是使asynctask成为活动本身的私有类,但我真的希望将它保持独立。 可重用性和什么不 –

有什么想法吗?

总结一下,在task.execute完成后需要doX()。 任何想法都赞赏。


d:

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

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

来自AsyncTask

 MyActivity.doX(); 

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

 CustomTask task = new CustomTask() { @Override protected void onPostExecute(Long result) { super.onPostExecute(result); MyActivity.this.doX(); } }.execute(); 

选项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线程并可能导致ANRexception。通过这样做,您实际上牺牲了AsyncTask的好处,并使其与UI线程同步运行。


选项B和C

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

AsyncTask,正如其名称所述,与UI线程异步运行后台线程,一旦后台线程完成,就在UI线程上调用onPostExecute方法。 在项目构建时没有办法确切地告诉onPostExecute方法何时被调用(即当doInBackground方法完成时),因为它是在应用程序运行时确定的,我们唯一知道的是onPostExecute方法保证在UI线程上调用在未来的某个时候,换句话说,当在项目构建时编写代码时,我们永远不知道doInBackground何时完成并且代码执行跳回到onPostExecute方法之外的UI线程(除非你在代码中实现一些等待机制,如Option一个)。 因此onPostExecute方法的目的是在doInBackground方法完成后处理所有内容,这也是为什么onPostExecute方法的唯一参数是doInBackground方法返回的结果。

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

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

选项B通常更安全。 但即便如此,你还需要小心。 您需要在ASyncTask存储Activity实例 (而不仅仅是类)。 如果Activity在任务运行时被销毁(如果用户按下Back按钮怎么办?),你需要通知任务这个任务,所以任务不会尝试在死Activity上调用方法。

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

这些事情很繁琐。

我能够通过界面实现此function:

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

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

然后在你的例程代码中放入一个新的Callbacks实例:

 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 !!! } });