63

我正在尝试在 Android 上实现加载程序示例,但无法启动加载程序。我正在使用以下代码。它会点击“Create Loader”,但永远不会到达“Loading started”日志消息。我错过了我需要的电话吗?

活动:

    public class TestingZoneActivity extends ListActivity implements LoaderCallbacks<ArrayList<Content>>{

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

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

        @Override
        public Loader<ArrayList<Content>> onCreateLoader(int id, Bundle args) {
            Log.e("TEST", "Create Loader");
            return new ImageLoader(this);
        }

        @Override
        public void onLoadFinished(Loader<ArrayList<Content>> loader, ArrayList<Content> data) {
            setListAdapter(new ImageAdapter(this, data));
        }

        @Override
        public void onLoaderReset(Loader<ArrayList<Content>> loader) {
            setListAdapter(null);
        }
    }

装载机:

    public class ImageLoader extends AsyncTaskLoader<ArrayList<Content>> {

        public ImageLoader(Context context) {
            super(context);
        }

        @Override
        public ArrayList<Content> loadInBackground() {
            Log.e("TEST", "Loading started");
        }

    }
4

6 回答 6

131

我在使用兼容性库时遇到了同样的问题。我通过调用解决了它forceLoad

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

显然 AsyncLoader 上的文档是缺失的,而且 HoneyComb 上也存在这个问题。更多信息可以在这里找到

AsyncTaskLoader的官方示例也是调用 forceLoad() 所以它不是一个错误,但我仍然认为这种行为不是很直观。

于 2012-05-10T15:30:51.920 回答
26

覆盖loadInBackground()是不够的。

看看http://developer.android.com/reference/android/content/AsyncTaskLoader.htmlAppListLoader_

至少将这两种方法添加到您的加载程序中:

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

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

onContentChanged()从其构造函数调用。

于 2013-05-17T17:41:09.877 回答
14

rayst的建议非常紧凑。如果你这样写你的方法:

protected void onStartLoading() {
    forceLoad();
}

您会注意到,当子活动出现然后您返回父活动时,onStartLoading(因此loadInBackground)再次被调用!

你能做什么?在构造函数内部将一个内部变量 ( mContentChanged) 设置为 true;然后在里面检查这个变量onStartLoading。只有当它为真时,才开始真正加载:

package example.util;

import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;

public abstract class ATLoader<D> extends AsyncTaskLoader<D> {

    public ATLoader(Context context) {
        super(context);
        // run only once
        onContentChanged();
    }

    @Override
    protected void onStartLoading() {
        // That's how we start every AsyncTaskLoader...
        // -  code snippet from  android.content.CursorLoader  (method  onStartLoading)
        if (takeContentChanged()) {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }
}
于 2013-10-20T18:36:26.893 回答
3

由于这里没有一个答案(除了接受的答案)单独帮助我解决了这个问题,这就是它对我的工作方式。

我不认为接受的答案是正确的解决方案,因为它会导致loadInBackground()调用频率超过必要,即在方向更改时,这在加载程序中正确覆盖以下方法时也不会发生:

@Override
public void deliverResult(final List<Participant> data) {
    participants = data;

    if (isStarted()) {
        super.deliverResult(data);
    }

}

@Override
protected void onStartLoading() {
    if (takeContentChanged() || participants == null) {
        forceLoad();
    }
}
于 2015-09-02T15:12:06.573 回答
0

如果您使用的是自定义加载器,则可以保存最后一个数据引用,并通过 getter 使其可用。当用户旋转他的屏幕时,您可以从 getLoaderManager().getLoader 方法中获取加载器,然后返回引用。对于我的测试,我注意到 startLoadering 一直到 CustomLoader.onLoadFinished 但结果永远不会传递给 activity.onLoadFinished。我怀疑活动参考在旋转时会丢失。顺便说一句,创建加载器的好处是它们通过 LoaderManager 持久化。把它想象成另一种无头碎片的味道……哈哈。

Loader loader  =  getLoaderManager().getLoader(LOADER_ID);

if( loader == null )
{
    getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
}
else
{
    listAdapter.addAll(((CustomLoader) loader).getLastData());
}
于 2015-08-03T16:50:26.190 回答
0

我发现上述每个解决方案都有问题,尤其是当应用程序在屏幕关闭时启动,并且加载需要一些时间。

这是我的解决方案(基于):

https://stackoverflow.com/a/22675607/878126

于 2016-03-30T09:05:25.427 回答