@Background and screen rotation when using AndroidAnnotations, how to make sure that the callbacks are received?

StackOverflow https://stackoverflow.com/questions/10151578

Question

When using the @Background annotation we start a new thread. And if we while this thread is executing where to rotate the screen, will we then lose the callback from that thread or how is that handled? With the Loaders this is sorted out behind the screen so we don't have to worry about the problems that occurred frequently back when we used async tasks.

But how does the @Background annotation deal with this ?

Was it helpful?

Solution

First of all, when you use the @Background annotation, the code is executed on a separate thread, but this doesn't necessarily mean that a new thread will be started, because we use a common thread pool (which can be replaced) for all @Background methods.

Like an AsyncTask, @Background does not handle any lifecycle changes on your activities. So, if you call an @Background method and then the screen is rotated, then the @Background code will be executed, no matter what, on the instance it was called on. If @Background is placed on a method that belongs to the activity, and in turns call a @UiThread method, there is a risk that the @UiThread method will be called on the wrong activity instance, if a configuration change occurred.

In Android, prior to Loaders, the usual way to handle that was to use AsyncTask, keep references to those tasks in onRetainNonConfigurationInstance(), and rebind them to the new activity after a config change.

In the latest release, AndroidAnnotations provides the @NonConfiguration instance annotation, which can be combined with @EBean / @Bean and @Background to achieve the same effect.

Here is a sample code (not tested, written from 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);
  }
}

I think we could provide even better solutions, but there are a lot of different use cases, and we need to think about them all. So right now, @Background has a very simple behavior and I don't want to change that. We could, however, introduce new annotations with an advanced "thread + lifecycle" behavior.

Thanx to "Pierre-Yves Ricau" for providing this answer via the googlegroup for androidannotations. Hope this will help others who might get stuck with a similar problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top