Android AsyncTaskLoader第三个任务消失

Android AsyncTaskLoader第三个任务消失,android,android-loadermanager,asynctaskloader,android-loader,Android,Android Loadermanager,Asynctaskloader,Android Loader,我正在尝试实现一个列表/详细信息工作流,其中点击列表项会导致详细信息部分加载与新选定行相关的数据。我正试图使用AsyncTaskLoader来实现这一点。我遇到了一个问题,如果我在一行中足够快地点击三个列表项,实际上只有两个加载发生,第三个加载丢失 我已经编写了一个示例活动来演示这种行为。当点击按钮三次时,loadInBackground()方法只会被调用两次。我是不是错过了一个电话 public final class LoaderActivity extends Activity imple

我正在尝试实现一个列表/详细信息工作流,其中点击列表项会导致详细信息部分加载与新选定行相关的数据。我正试图使用
AsyncTaskLoader
来实现这一点。我遇到了一个问题,如果我在一行中足够快地点击三个列表项,实际上只有两个加载发生,第三个加载丢失

我已经编写了一个示例活动来演示这种行为。当点击按钮三次时,
loadInBackground()
方法只会被调用两次。我是不是错过了一个电话

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);
            }
        }

    }

}
公共最终类LoaderActivity扩展活动实现LoaderManager.LoaderCallbacks{
私人按钮;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.loader);
按钮=(按钮)findViewById(R.id.load_按钮);
getLoaderManager().initLoader(0,null,this);
}
公共作废按钮单击(查看源){
Loader Loader=getLoaderManager().getLoader(0);
if(加载程序!=null){
loader.forceLoad();
}
}
@凌驾
公共加载器onCreateLoader(int-id,Bundle-args){
返回新的IntLoader(此);
}
@凌驾
public void onLoadFinished(加载器listLoader,整数数据){
button.setText(String.valueOf(data));
}
@凌驾
public void onLoaderReset(加载程序列表加载程序){
}
私有静态最终类IntLoader扩展了AsyncTaskLoader{
私有静态最终AtomicInteger计数器=新的AtomicInteger(0);
IntLoader(上下文){
超级(上下文);
}
@凌驾
公共整数loadInBackground(){
int result=counter.getAndIncrement();
//模拟一个可能昂贵的web调用
试一试{
睡眠(5000);
}捕捉(中断异常e){
}
返回结果;
}
@凌驾
受保护的无效onStopLoading(){
取消加载();
}
@凌驾
受保护的void onReset(){
onStopLoading();
}
@凌驾
公共void deliverResult(整数数据){
如果(isStarted()){
super.deliverResult(数据);
}
}
}
}

调用
restartLoader(0,null,this)
而不是
onButtonClick()
方法中的
getLoader(0)
似乎解决了这个问题。随着我对
Loader
s的了解越来越多,调用它似乎是更合适的方法,因为我想在这一点上放弃任何旧的结果。

您确定该方法只被调用了两次吗?或者消息可能被调用了3次,但只有2次用户界面被调用
setText
更新<默认情况下,code>onLoadFinished未与UI线程同步,这就是我感到奇怪的原因。绝对可以肯定的是,
loadInBackground()
只被调用了两次-我在
loadInBackground()
的开头设置了一个断点。(好吧,事实上我不是100%确定
onLoadFinished
是否在主UI线程上被调用…这似乎是一个混乱的来源,因为Commonware和Reto-Meier在他们的书中都站在相反的一边哈哈…我会就此回复你。)顺便问一句,你不应该调用
forceLoad()吗
onStartLoading
中?当活动启动时,实际上没有什么可以加载的。直到选择了列表项(或者在我设计的示例中点击了按钮),才需要进行实际加载。我还是应该从
onStartLoading()
调用
forceLoad()