Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loader: onLoadFinished called only once

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.

like image 649
Sababado Avatar asked Dec 16 '13 19:12

Sababado


1 Answers

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

Thanks for pointing this out!

like image 119
CommonsWare Avatar answered Oct 18 '22 21:10

CommonsWare