30

我想使用 Compatibility Package 在我的项目中实现 AsyncTaskLoader,所以我遵循了 Android Docs 中的 Loader 手册。

问题是 Loader 什么都不做,似乎loadInBackground()从来没有被调用过

知道我的代码有什么问题吗?(ExpandableListFragment扩展Fragment,但不覆盖任何关键方法)

谢谢 :-)

/**编辑:

我意识到(晚了,我是个白痴)AsyncTaskLoader 是一个抽象类,所以我需要对它进行子类化...... m(__)m 我留下这个问题,以防有人在我身后来到这里,谁知道......

public class AgendaListFragment extends ExpandableListFragment implements
        LoaderManager.LoaderCallbacks<JSONArray> {

    private TreeMap<Integer, ArrayList<Evento>> mItems = new TreeMap<Integer, ArrayList<Evento>>();
    private AgendaListAdapter mAdapter;
    private ProgressBar mProgressBar;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_agenda, container);
        mProgressBar = (ProgressBar) root.findViewById(R.id.loading);
        return root;

    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mAdapter = new AgendaListAdapter(getActivity());
        setListAdapter(mAdapter);

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

    }

    @Override
    public Loader<JSONArray> onCreateLoader(int arg0, Bundle arg1) {
        mProgressBar.setVisibility(View.VISIBLE);
        return new AsyncTaskLoader<JSONArray>(getActivity()) {
            @Override
            public JSONArray loadInBackground() {

                return getDataFromService(AgendaServices.LISTADO_MES);

            }

        };
    }

    @Override
    public void onLoadFinished(Loader<JSONArray> loader, JSONArray data) {

        // Some stuff to turn JSONArray into TreeMap

        mProgressBar.setVisibility(View.GONE);
        mAdapter.setItems(mItems);

    }

    @Override
    public void onLoaderReset(Loader<JSONArray> arg0) {
        mAdapter.setItems(null);
        mProgressBar.setVisibility(View.VISIBLE);

    }

}
4

7 回答 7

63

我认为 Compatibility 包的最佳解决方案是覆盖AsyncTaskLoader.onStartLoading方法。

例如

@Override
protected void onStartLoading() {
  if(dataIsReady) {
    deliverResult(data);
  } else {
    forceLoad();
  }
}
于 2012-01-12T05:55:47.310 回答
8

这完全是一个修复,但它应该可以工作。我很确定兼容性库已损坏。试试这个:

getLoaderManager().initLoader(0, null, this).forceLoad();
于 2011-12-27T00:40:42.817 回答
3

卓彦诚绝对正确:

检查 takeContentChanged 似乎也是重要的一步。

如果你这样写你的方法:

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();
        }
    }
}
于 2013-10-20T18:10:23.707 回答
1

查看https://code.google.com/p/android/issues/detail?id=14944的讨论,检查takeContentChanged似乎也是重要的一步。

protected void onStartLoading() {
    if (mCursor != null) {
        deliverResult(mCursor);
    }
    if (takeContentChanged() || mCursor == null) {
        forceLoad();
    }
}
于 2013-03-19T07:26:21.090 回答
0

CursorLoader我从android框架中获取了源代码,并编写了一个CustomTaskLoader<T>类来简化工作。

https://github.com/Palatis/danbooru-gallery-android/blob/new_api/DanbooruGallery/src/main/java/tw/idv/palatis/danboorugallery/android/content/CustomTaskLoader.java

你基本上实现了这两个功能:

public abstract T runTaskInBackground(CancellationSignal signal);
public abstract void cleanUp(T oldResult);

查看活动和片段中的用法,例如这个:(我的代码只是忽略了CancellationSignal,它TODO在我的列表中,但您可以自由使用它。)

https://github.com/Palatis/danbooru-gallery-android/blob/new_api/DanbooruGallery/src/main/java/tw/idv/palatis/danboorugallery/PostListFragment.java

return new CustomTaskLoader<Cursor>(getActivity().getApplicationContext()) 
{
    @Override
    public Cursor runTaskInBackground(CancellationSignal signal)
    {
        return SiteSession.getAllPostsCursor(PostListAdapter.POST_COLUMNS);
    }

    @Override
    public void cleanUp(Cursor oldCursor)
    {
        if (!oldCursor.isClosed())
            oldCursor.close();
    }
}
于 2014-01-31T08:41:47.383 回答
0

从 CursorLoader 迁移到 AsyncTaskLoader 后,我遇到了同样的问题。

文档说子类Loader<D>通常必须至少实现onStartLoading()、onStopLoading()、onForceLoad() 和 onReset()

AsyncTaskLoader 扩展了 Loader 但没有实现onStartLoading(), onStopLoading(), onReset()。你必须自己实现它!

@davidshen84 提出了很好的解决方案。我只添加了对 takeContentChanged 的​​检查。

@Override
protected void onStartLoading() {
    try {
        if (data != null) {
            deliverResult(data);
        }
        if (takeContentChanged() || data == null) {
            forceLoad();
        }

        Log.d(TAG, "onStartLoading() ");
    } catch (Exception e) {
        Log.d(TAG, e.getMessage());
    }
}

使用 forceLoad() 是可以的(不是一个坏习惯)。查看文档中的内容:您通常应该只在加载程序启动时调用它 - 即 isStarted() 返回 true

于 2016-08-17T10:31:06.467 回答
-2

我仍然遇到未调用数据加载的问题。我终于删除了AsyncTaskLoader(支持库版本)并仅使用AsyncTask(不是来自支持库)来完成这项工作。它奏效了。

它也可能足以满足您的需求。

说明和示例:http: //developer.android.com/reference/android/os/AsyncTask.html

您必须扩展类AsyncTask

doInBackground方法将完成工作,在onPostExecute方法中您将获得结果。为了启动AsyncTask,您将在其实例上调用方法execute 。请参阅链接。

于 2013-07-01T06:10:00.857 回答