Вопрос

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