AsyncTaskLoader不运行

时间:2011-12-22 15:31:32

标签: android asynctaskloader

我想使用兼容包在我的项目中实现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);

    }

}

7 个答案:

答案 0 :(得分:63)

我认为兼容性套件的最佳解决方案是覆盖 AsyncTaskLoader.onStartLoading 方法。

e.g。

@Override
protected void onStartLoading() {
  if(dataIsReady) {
    deliverResult(data);
  } else {
    forceLoad();
  }
}

答案 1 :(得分:8)

这只是一个修复,但它应该工作。我很确定兼容性库已被破坏。试试这个:

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

答案 2 :(得分:3)

Cheok Yan Cheng绝对正确:

  

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

答案 3 :(得分: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();
    }
}

答案 4 :(得分:0)

我从android框架中获取了CursorLoader的源代码,并编写了一个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();
    }
}

答案 5 :(得分:0)

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

documentation says 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()是可以的(这不是一个坏习惯)。查看文档says
通常只应在加载程序启动时调用它 - 也就是说,isStarted()返回true。

答案 6 :(得分:-2)

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

这也足以满足您的需求。

描述和示例:http://developer.android.com/reference/android/os/AsyncTask.html

您必须扩展课程 AsyncTask

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