Android AsyncTaskLoader无法启动loadInBackground?

时间:2012-05-09 21:57:23

标签: java android

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

的活动:

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

    }

6 个答案:

答案 0 :(得分:128)

使用兼容性库时遇到了同样的问题。 我通过致电forceLoad

解决了这个问题
getLoaderManager().initLoader(0, null, this).forceLoad();

显然缺少AsyncLoader的文档,HoneyComb上也存在这个问题。可以找到更多信息here

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

答案 1 :(得分:25)

覆盖loadInBackground()是不够的。

查看http://developer.android.com/reference/android/content/AsyncTaskLoader.html上的AppListLoader

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

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

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

并从其构造函数中调用onContentChanged()

答案 2 :(得分:13)

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

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

答案 3 :(得分:2)

由于这里的答案(除了被接受的答案)都没有帮助我解决这个问题,因此以下是它对我有用的方法。

我不认为接受的答案是正确的解决方案,因为它导致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();
    }
}

答案 4 :(得分:0)

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

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

if( loader == null )
{
    getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
}
else
{
    listAdapter.addAll(((CustomLoader) loader).getLastData());
}

答案 5 :(得分:0)

我发现上述每种解决方案都存在问题,尤其是在屏幕关闭时应用启动时,加载需要一些时间。

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

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