Android: LoaderCallbacks.OnLoadFinished called twice

前端 未结 10 2263
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-04 11:05

I noticed strange situation using Android Loaders and Fragments. When I invoke LoaderManager.initLoader() after orientation change onLoadFinished is not called (although doc

相关标签:
10条回答
  • 2020-12-04 11:14

    The problem is that it called twice:
    1. from Fragment.onStart
    2. from FragmentActivity.onStart

    The only difference is that in Fragment.onStart it checks if mLoaderManager != null. What this means is if you call getLoadManager before onStart, like in onActivityCreated, it will get/create load manager and it will be called. To avoid this you need to call it later, like in onResume.

    0 讨论(0)
  • 2020-12-04 11:21

    You can put the initLoader() method inside your Fragment's onResume() callback; then the Loader's onLoadFinished() will not be called twice anymore.

        @Override
    public void onResume()
    {
        super.onResume();
        getLoaderManager().initLoader(0, null, this);
    }
    
    0 讨论(0)
  • 2020-12-04 11:21

    initLoader documentation says,

    If at the point of call the caller is in its started state, and the requested loader already exists and has generated its data, then callback onLoadFinished(Loader, D)

    I suggest you to implement something like onStartLoading function at this sample

    For quick test you can try:

    @Override protected void onStartLoading() {
        forceLoad();
    }
    

    This launch loadInBackground function and then onLoadFinished in Fragment.

    Any way, if you attach some code i'll try to give you more help.

    0 讨论(0)
  • 2020-12-04 11:27

    i have face this issue.but i while used to call the destroyloader(YOUR_ID) in loaderfinished methods. then the loader not again call the backgrdound task twice.

    0 讨论(0)
  • 2020-12-04 11:28

    This problem manifested itself for me with a CursorLoader returning a Cursor that was already closed:

    android.database.StaleDataException: Attempted to access a cursor after it has been closed.
    

    I'd guess this is a bug or an oversight. While moving initLoader() into onResume may work, what I was able to do was remove the Loader when I'm done with it:

    To start the loader (in my onCreate):

      getLoaderManager().initLoader(MUSIC_LOADER_ID, null, this);
    

    Then after I'm done with it (basically at the end of onLoadFinished)

      getLoaderManager().destroyLoader(MUSIC_LOADER_ID);
    

    This seems to behave as expected, no extra calls.

    0 讨论(0)
  • 2020-12-04 11:32

    I solved the problem of onLoadFinished being called twice like this. In your Fragment.onActivityCreated() init your Loader like this

    if (getLoaderManager().getLoader(LOADER_ID) == null) {
        getLoaderManager().initLoader(LOADER_ID, bundle, loaderCallbacks);
    } else {
        getLoaderManager().restartLoader(LOADER_ID, bundle, loaderCallbacks);
    
    }
    

    here loaderCallbacks implements your usual Loader callbacks

    private LoaderManager.LoaderCallbacks<T> loaderCallbacks
            = new LoaderManager.LoaderCallbacks<T>() {
        @Override
        public Loader<T> onCreateLoader(int id, Bundle args) {
            ...
            ...
        }
    
        @Override
        public void onLoadFinished(Loader<T> loader, T data) {
            ...
            ...
        }
    
        @Override
        public void onLoaderReset(Loader<T> loader) {
            ...
            ...
        }
    };
    
    0 讨论(0)
提交回复
热议问题