我想使用兼容包在我的项目中实现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);
}
}
答案 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>
类来简化这项工作。
你基本上实现了这两个功能:
public abstract T runTaskInBackground(CancellationSignal signal);
public abstract void cleanUp(T oldResult);
查看活动和片段中的用法,例如:
(我的代码只是忽略CancellationSignal
,我的列表中只有TODO
,但您可以自由使用它。)
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 ,您将在其实例上调用方法执行。请参阅链接。