Loader unable to retain itself during certain configuration change

前端 未结 4 611
渐次进展
渐次进展 2020-12-13 06:59

According to http://developer.android.com/guide/components/loaders.html, one of the nice thing about loader is that, it is able to retain its data during configuration chang

相关标签:
4条回答
  • 2020-12-13 07:34

    If you are using FragmentManager's replace fragment technique this issue will happen.

    When you replace/remove the Fragment, the fragment is detached from the activity and since loaders are attached to the activity, the loaders will be recreated during orientation change.

    Try using FragmentManager's hide/show technique. May be this will help you.

    0 讨论(0)
  • 2020-12-13 07:40

    My answer is quite straight forward actually. Don't use AsyncTaskLoaders. Because a few bugs regarding AsyncTaskLoaders you knew it by now.

    A good combination would be a retainable (setRetainInstance(true) in onActivityCreated()) fragment with AsyncTask. Works the same way. Just have to restructure the code a bit.


    Message from OP

    Although the author doesn't provide any code example, this is the closest workable solution. I do not use the author proposed solution. Instead, I still rely on AsyncTaskLoader for all the necessary loading task. The workaround is that, I will rely on an additional retained fragment, to determine whether I should reconnect/create loader. The is the skeleton code on the whole idea. Works pretty well so far as long as I can tell.

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        ...
    
        dataRetainedFragment = (DataRetainedFragment)fm.findFragmentByTag(DATE_RETAINED_FRAGMENT);
        // dataRetainedFragment can be null still...
    }
    
    @Override
    public void onResume() {
        ...
        if (this.data == null) {
            if (dataRetainedFragment != null) {
                // Re-use!
                onLoadFinished(null, dataRetainedFragment);
            } else {
                // Prepare the loader.  Either re-connect with an existing one,
                // or start a new one.
                getLoaderManager().initLoader(0, null, this);
            }
        } else {
        }
    }
    
    @Override
    public void onLoadFinished(Loader<Data> arg0, Data data) {
        this.data = data;
    
        if (this.dataRetainedFragment == null) {
            this.dataRetainedFragment = DataRetainedFragment.newInstance(this.data);
            FragmentManager fm = getFragmentManager();
            fm.beginTransaction().add(this.dataRetainedFragment, DATE_RETAINED_FRAGMENT).commitAllowingStateLoss();            
        }
    
    0 讨论(0)
  • 2020-12-13 07:43

    Try to change,

     @Override
    public void onResume()
    {
        super.onResume();
    
        if (result == null) {
            // Prepare the loader.  Either re-connect with an existing one,
            // or start a new one.
            getLoaderManager().initLoader(0, null, this);
        } else {
            // Restore from previous state. Perhaps through long pressed home
            // button.
        }
    }    
    

    to

     @Override
    public void onResume()
    {
        super.onResume();
    
    Loader loader = getLoaderManager().getLoader(0); 
    if ( loader != null && loader.isReset() ) { 
        getLoaderManager().restartLoader(0, getArguments(), this); 
    } else { 
        getLoaderManager().initLoader(0, getArguments(), this); 
    } 
    
    }    
    
    0 讨论(0)
  • 2020-12-13 07:44

    I've had success subclassing AsyncTaskLoader and making a few tweaks to its methods.

    public class FixedAsyncTaskLoader<D> extends AsyncTaskLoader<D> {
    
        private D result;
    
        public FixedAsyncTaskLoader(Context context) {
            super(context);
        }
    
        @Override
        protected void onStartLoading() {
            if (result != null) {
                deliverResult(result);
            } else {
                forceLoad();
            }
        }
    
        @Override
        public void deliverResult(T data) {
            result = data;
    
            if (isStarted()) {
                super.deliverResult(result);
            }
        }
    
        @Override
        protected void onReset() {
            super.onReset();
            onStopLoading();
    
            result = null;
        }
    
        @Override
        protected void onStopLoading() {
            cancelLoad();
        }
    }
    
    0 讨论(0)
提交回复
热议问题