0

I have an AsyncTaskLoader that is being reset in a very specific case, and was hoping someone may be able to tell me why.

  1. In my activity, I am calling getSupportLoaderManager().initLoader(0, null, this) in the onCreate() method. Everything runs as expected:
D/Activity﹕ calling initLoader()
D/Activity﹕ onCreateLoader()
D/Loader﹕ onStartLoading()
D/Loader﹕ onStartLoading(): no data, forcing load
D/Loader﹕ loadInBackground()
D/Activity﹕ onLoadFinished()
  1. But if I background the app (hit home), rotate the device, and then return it to the foreground, I'm seeing the loader is reset:
D/Activity﹕ onLoaderReset()
D/Activity﹕ calling initLoader()
D/Activity﹕ onCreateLoader()
D/Loader﹕ onStartLoading()
D/Loader﹕ onStartLoading(): no data, forcing load
D/Loader﹕ loadInBackground()
D/Activity﹕ onLoadFinished()

The loader isn't reset when the app is sent to the background and restored (in the same orientation) and it's not reset when rotating the device while the app is in the foreground. Thus, I wouldn't expect it to be reset in the circumstances described in #2.

Can anyone provide any insight? I'm trying to prevent the app from making an unnecessary call in the off change that someone backgrounds the app, rotates the device, and and then restores the app. Thanks

abe
  • 1,549
  • 1
  • 11
  • 9
  • Is OnCreate() also being called when this happens? – l-l Apr 08 '15 at 00:10
  • Yeah, onCreate() is being called – abe Apr 08 '15 at 00:28
  • Well for some reason you activity is being recreated. You should account for this case in you code. I'll post an answer – l-l Apr 08 '15 at 00:32
  • The activity is destroyed and recreated when rotated. This is normal and expected. The problem is that the loader is being reset when rotated while the app is not visible. – abe Apr 08 '15 at 00:53

2 Answers2

0

Sometimes the device will destroy the an activity and then restore it when the user returns. You need to restore your state when its recreated. If you have variables that you need to save then you need to override this method:

    @Override
    public void onSaveInstanceState (Bundle outState) {
        // save you variables
        outState.putInt("myInt", myInt);
    }

So when the activity is recreated you would check if savedInstanceState is null. If it null you can initialize as usual, if not you can restore your state. For you case if savedInstanceState is not null you wouldn't init the loader

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(savedInstanceState != null) {
        // restore state
    } else {
        // init your loader
    }

}
l-l
  • 3,804
  • 6
  • 36
  • 42
0

This question's still open so here's my answer. I tried your usecase (2) and my AsyncTaskLoader doesn't reset. Note that I'm overriding the callbacks to save the App Instance state as well.

If you've initialized the loader properly I suspect that you're probably not saving App Instance state. When you send your app to the background, that is an indication to the Android system that your app may be destroyed. Even though it is paused, the Android system can take a decision depending on the system's resources, current load and a host of other conditions to move it from the paused state to the stopped state and free up resources. That's what could be happening in your case.

Anyway here's how I've used the loader functions. There's initLoader() and restartLoader().

With initLoader() you need to do a check before calling it and with restartLoader() you will need to pass a Bundle to the call.

So

if(getSupportLoaderManager().getLoader(0) != null)
  {
    getSupportLoaderManager.initLoader(0,null,this);
  }

and for the fresh restarts

   Bundle mybundle = new Bundle();
   mybundle.putString("somekey", "someval");
   getSupportLoaderManager.restartLoader(0,mybundle,this);

I assuming the AsyncTaskLoader setup and the implementation of Loader callbacks is done properly.

pcodex
  • 1,812
  • 15
  • 16