4

使用 @Background 注释时,我们启动一个新线程。如果我们在这个线程执行旋转屏幕的时候,我们会丢失来自那个线程的回调吗?或者如何处理?使用 Loaders,这在屏幕后面进行了整理,因此我们不必担心使用异步任务时经常发生的问题。

但是@Background 注释是如何处理这个问题的呢?

4

1 回答 1

6

首先,当你使用@Background注解时,代码是在单独的线程上执行的,但这并不一定意味着会启动一个新的线程,因为我们使用了一个普通的线程池(可以替换)所有@Background 方法。

与 AsyncTask 一样,@Background 不会处理您的活动的任何生命周期更改。因此,如果您调用@Background 方法然后旋转屏幕,那么无论如何都会在调用它的实例上执行@Background 代码。如果将@Background 放置在属于该活动的方法上,并依次调用@UiThread 方法,则如果发生配置更改,则可能会在错误的活动实例上调用@UiThread 方法。

在 Android 中,在加载器之前,通常的处理方法是使用 AsyncTask,在 onRetainNonConfigurationInstance() 中保留对这些任务的引用,并在配置更改后将它们重新绑定到新活动。

在最新版本中,AndroidAnnotations 提供了@NonConfiguration 实例注解,可以与@EBean / @Bean 和@Background 组合使用,达到同样的效果。

这是一个示例代码(未经测试,由 gmail 编写):

@EActivity
public class MyActivity extends Activity {

  // Using @NonConfigurationInstance on a @Bean will automatically update the context ref on configuration changes (if the bean is not a singleton)
  @NonConfigurationInstance
  @Bean
  MyBackgroundTask task;

  @Click
  void myButtonClicked() {
    task.doSomethingInBackground();
  }

  void showResult(MyResult result) {
    // do something with result
  }

}


@EBean
public void MyBackgroundTask {

  @RootContext
  MyActivity activity;

  @Background
  void doSomethingInBackground() {
      // do something
     MyResult result = XXX;

      updateUI(result);
  }

  // Notice that we manipulate the activity ref only from the UI thread
  @UiThread
  void updateUI(MyResult result) {
    activity.showResult(result);
  }
}

我认为我们可以提供更好的解决方案,但是有很多不同的用例,我们需要全部考虑。所以现在,@Background 有一个非常简单的行为,我不想改变它。但是,我们可以引入具有高级“线程 + 生命周期”行为的新注释。

感谢“Pierre-Yves Ricau”通过 googlegroup 为 androidannotations 提供此答案。希望这将帮助其他可能遇到类似问题的人。

于 2012-04-14T06:32:11.353 回答