I'm trying to implement a list/detail workflow where a tap on a list item causes the detail section to load data related to the newly selected row. I'm trying to use an AsyncTaskLoader to accomplish this. I'm running into a problem where if I tap three list items quickly enough in a row, only two of the loads actually occur and the third gets lost.

I've written a sample activity that demonstrates this behavior. When tapping the button three times, the loadInBackground() method is only getting called twice. Am I missing a call somewhere?

public final class LoaderActivity extends Activity implements LoaderManager.LoaderCallbacks<Integer> {

    private Button button;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loader);

        button = (Button) findViewById(R.id.load_button);

        getLoaderManager().initLoader(0, null, this);
    }

    public void onButtonClick(View source) {
        Loader<Integer> loader = getLoaderManager().getLoader(0);
        if (loader != null) {
            loader.forceLoad();
        }
    }

    @Override
    public Loader<Integer> onCreateLoader(int id, Bundle args) {
        return new IntLoader(this);
    }

    @Override
    public void onLoadFinished(Loader<Integer> listLoader, Integer data) {
        button.setText(String.valueOf(data));
    }

    @Override
    public void onLoaderReset(Loader<Integer> listLoader) {

    }

    private static final class IntLoader extends AsyncTaskLoader<Integer> {

        private static final AtomicInteger counter = new AtomicInteger(0);

        IntLoader(Context context) {
            super(context);
        }

        @Override
        public Integer loadInBackground() {
            int result = counter.getAndIncrement();

            // Simulate a potentially expensive web call
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {

            }

            return result;
        }

        @Override
        protected void onStopLoading() {
            cancelLoad();
        }

        @Override
        protected void onReset() {
            onStopLoading();
        }

        @Override
        public void deliverResult(Integer data) {
            if (isStarted()) {
                super.deliverResult(data);
            }
        }

    }

}
有帮助吗?

解决方案

Calling restartLoader(0, null, this) instead of getLoader(0) in the onButtonClick() method seems to have solved this problem. As I'm learning more about Loaders it sounds like the more appropriate method to call since I'm wanting to discard any old results at that point.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top