Buckstabue
Buckstabue

Reputation: 303

How to get the result of a loader if the screen was rotated during its job?

I heard loaders can help save the result of an asynchronous job during orientation changes. I have a fragment that executes a loader with some arguments. What should I do to reconnect to the loader? Important note: I don't want to restart the loader if its result was already processed by the LoaderCallbacks.onLoadFinished().
More detailed: I have a fragment with a text field. When the user inputs some text and presses Enter I should start search with a network request. I do it by starting a loader

 private void loadFirstPage() {
    LoaderManager loaderManager = getLoaderManager();
    data.currentPage = 1;

    Bundle args = new Bundle();
    args.putString(VacanciesAsyncLoader.ARG_SEARCH_TEXT, data.query);
    args.putInt(VacanciesAsyncLoader.ARG_ITEMS_PER_PAGE, Const.ITEM_PER_PAGE);
    args.putInt(VacanciesAsyncLoader.ARG_PAGE_NUMBER, data.currentPage);
    loaderManager.restartLoader(GET_VACANCIES_LOADER_ID, args, this);
}

@Override
public void onViewCreated(Bundle savedInstanceState) {
    super.onViewCreated(savedInstanceState);
    if (savedInstanceState == null) {
        // ...
    } else {
        data = savedInstanceState.getParcelable(KEY_DATA);
        restoreViewState(data);
        reconnectLoaderIfNeeded();
    }
}

private void reconnectLoaderIfNeeded() {
    EnumSet<State> loadingStates =
            EnumSet.of(State.REFRESHING, State.LOADING_FIRST_PAGE, State.LOADING_ADDITIONAL_PAGE);
    if (loadingStates.contains(data.state)) {
        getLoaderManager().initLoader(GET_VACANCIES_LOADER_ID, null, this);
    }
}

And I want to reconnect to it when the screen rotates. And if I processed its result, I don't want to trigger it again.

Upvotes: 1

Views: 550

Answers (3)

Kevin Coppock
Kevin Coppock

Reputation: 134664

If this is just a one-off request, the typical pattern for this should be:

Initiate the request:

getLoaderManager().restartLoader(LOADER_ID, args, callbacks);

In onCreate(), check to see if the Loader is still running:

if (savedInstanceState != null) {
    // If it exists, init with null arguments (since they won't
    // be used) to reconnect the callbacks
    if (getLoaderManager().getLoader(LOADER_ID) != null) {
        getLoaderManager().initLoader(LOADER_ID, null, callbacks);
    }
}

In your onLoadFinished(), destroy the loader:

getLoaderManager().destroyLoader(LOADER_ID);

Assuming you've implemented your Loader properly, this should do the trick.

Upvotes: 4

The4thIceman
The4thIceman

Reputation: 3889

This article helped me a lot in dealing with orientation changes regarding asynchronous tasks. It has to do with retaining Fragments:

http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

Hope this helps you as it did me

Upvotes: 0

amuyu
amuyu

Reputation: 236

You set this code in your Activity (for fragment).

AndroidManifest.xml :

android:configChanges="orientation|keyboardHidden"
...
<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="orientation|keyboardHidden"
        >

Upvotes: 0

Related Questions