Loader: onLoadFinished called only once
Asked Answered
M

1

7

I have one loader being used in an activity. I'm able to start the loader and it onLoadFinished is called. When I update data and call onContentChanged in the loader i see that loadInBackground and deliverResult are both called. This is where the trail seems to stop. I don't receive any callback to onLoadFinished.

If I recreate the activity (aka orientation change, or relaunch) then it will behave the same way.

I'm using the support-v4 loader and loader manager.

My SharedPreferenceLoader based on CommonsWare's loader:

public class SharedPreferencesLoader extends AsyncTaskLoader<SharedPreferences>
        implements SharedPreferences.OnSharedPreferenceChangeListener {
    private SharedPreferences prefs = null;

    private static final String TAG = SharedPreferencesLoader.class.getSimpleName();

    public SharedPreferencesLoader(Context context) {
        super(context);
    }

    @Override
    public SharedPreferences loadInBackground() {
        Log.v(TAG, "wol: load in background");
        prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
        prefs.registerOnSharedPreferenceChangeListener(this);

        return (prefs);
    }

    @Override
    protected void onStartLoading() {
        if (prefs != null) {
            deliverResult(prefs);
        }

        if (takeContentChanged() || prefs == null) {
            forceLoad();
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        Log.v(TAG, "wol: on shared preference changed.");
        onContentChanged();
    }
}

Here is how the loader is being used:

public class MainActivity extends ActionBarActivity implements
        LoaderManager.LoaderCallbacks<SharedPreferences> {
    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getSupportLoaderManager().initLoader(0, null, this);
        // fetch list of locations through an intent service.
        // This will save data to shared preferences and trigger onContentChanged
        MyIntentService.startActionGetLocations(this);
    }

    @Override
    public Loader<SharedPreferences> onCreateLoader(int i, Bundle bundle) {
        return new SharedPreferencesLoader(this);
    }

    @Override
    public void onLoadFinished(final Loader<SharedPreferences> sharedPreferencesLoader, final SharedPreferences sharedPreferences) {
        final List<PwStructure> locations = SharedPreferencesUtils.getLocations(sharedPreferences, this);
        Log.v(TAG, "wol: on load finished: "+locations);
        /* Do something with data. */
    }

    @Override
    public void onLoaderReset(final Loader<SharedPreferences> sharedPreferencesLoader) {
    }
}

Update I found this in the LoaderManager source. It looks as if the call to onLoadFinished isn't called if the data has the same reference.

Mountbatten answered 16/12, 2013 at 19:17 Comment(1)
+1 for the Update. I was not sure why my onLoadFinished is not called.Thanks alotPromising
A
4

Yes, it would appear that with the current LoaderManager implementation, SharedPreferencesLoader is pretty much screwed. I'll deprecate it.

Thanks for pointing this out!

Absinthe answered 16/12, 2013 at 23:25 Comment(1)
Ha! Awesome. Thank you and I appreciate the honesty. I ended up creating a StringPreferenceLoader. This is specific to my needs but it does the job well. github.com/sababado/CustomLoadersMountbatten

© 2022 - 2024 — McMap. All rights reserved.