首先,我要指出,我使用的向后兼容性的ActionBarSherlock库。
我还增加了一个活动ListFragment
时,首次启动它。 我有一个自定义Loader
我实现并遵循AsnycTaskLoader例子非常密切。 我的ListFragment
实现LoaderCallbacks<Cursor>
接口。 当加入片段被称为所有适当的回调方法( onCreateLoader()
onLoaderFinished()
当它被替换( onLoaderReset()
我onActivityCreated(Bundle)
方法如下:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAccountsDbAdapter = new AccountsDbAdapter(getActivity().getApplicationContext());
setHasOptionsMenu(true);
mCursorAdapter = new AccountsCursorAdapter(getActivity()
.getApplicationContext(), R.layout.list_item_account, null,
new String[] { DatabaseHelper.KEY_NAME },
new int[] { R.id.account_name }, 0);
setListAdapter(mCursorAdapter);
getLoaderManager().initLoader(0, null, this);
}
稍后, ListFragment
被替换为另一个片段B.当用户按下返回按钮,片段B被移除并且ListFragment再次添加。 然而,该列表是空的,只有android:empty
要显示的元素,没有的LoaderCallback方法被调用。 我可以使用调试器来确定getLoaderManager().initLoader(0, null, this);
实际上是调用,但没有别的。 当我将其更改为getLoaderManager().restartLoader(0, null, this);
,回调被调用,但是我的列表保持为空(虽然有数据,视图不会刷新)。
我怎样才能让我的ListFragment刷新自己,当它返回到布局? 有没有人遇到过这个,你是怎么解决这个问题?
仅供参考,这里有我的回调方法
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new AccountsCursorLoader(this.getActivity()
.getApplicationContext());
}
@Override
public void onLoadFinished(Loader<Cursor> loaderCursor, Cursor cursor) {
mCursorAdapter.swapCursor(cursor);
mCursorAdapter.notifyDataSetChanged();
}
@Override
public void onLoaderReset(Loader<Cursor> arg0) {
mCursorAdapter.swapCursor(null);
}
一些注意事项:
- 我不能使用
setListShown(true)
,因为我得到的实例方法IllegalStateException
,它不能用自定义内容视图中使用。 - 我
AccountsCursorAdapter
延伸SimpleCursorAdapter
并修改只有bindView()
方法。
尤里卡! 我发现它(意外,当然)
TL; DR;
在AccountsListFragment ,我现在创建我的数据库适配器( AccountsDatabaseAdapter
中) onCreate()
方法,并在其关闭onDestroy()
方法,它现在的作品。 以前我是我创造的适配器onActivityCreated()
和关闭onDestroyView()
请注意,我不是指ListAdapter
,而是我的数据库接口AccountsDbAdapter
。
尝试在长的解释:
好吧,我这样做是因为我觉得通过越来越上下文getActivity()
的将是不可能onCreate()
方法。 事实证明,你可以getActivity()
甚至在onActivityCreated()
被调用。
但我真的不能解释为什么这现在工作,因为Loader
有它自己的DatabaseAdapter
它用来检索数据对象。 如果我猜,我会说,同一个数据库对象返回两个数据库适配器( 数据库高速缓存 )。 这意味着,当我关闭一个在onDestroyView()
另一个也被关闭,光标数据集变得无效,导致一个空列表视图。 装载机不会重新加载,因为它认为该数据并没有改变。
但是,即使这种解释不符合我完全,因为这里的一些建议的解决方案,我试图像力重新加载每次没有工作。 (在loadInBackground()
方法,一个新的DatabaseAdapter
创建的每个时间)。
无论如何,如果你碰巧有一个更好的了解是怎么回事的,请在评论锤离开。
感谢大家与此帮助!
您是否尝试迫使装载机在你的活动重新启动,基础数据集更改后?
尝试:
getLoaderManager().restartLoader(0, null, this);
尝试的forceload() :
getLoaderManager().getLoader( 0 ).forceLoad();
什么适配器能看到:
为什么你看到一个空的ListView的原因是因为在返回的光标位置仍处于最后一个元素指向 。 当你swap()
光标的适配器,适配器将尝试使用迭代while(Cursor.moveToNext())
循环。 因为循环总是判断为假,你的ListView给你一个空指针的错觉。
打印的值Cursor.getCount()
和Cursor.getPosition()
在onLoadFinished()
如果我是正确的,这两个值应该是相等的。 指数的这种冲突造成上述假象。
为什么适配器看到这一点:
装载机将尽可能重新使用游标。 如果您要求的装载机一组数据并没有改变,装载机是聪明的,并返回通过onLoadFinished光标没有做任何额外的工作,甚至没有光标的位置设置为-1。
ANS呼叫Cursor.moveToPosition(-1)
在onLoadFinished()
手动来解决这个问题。
在我来说,我发现ListView控件根本没有屏幕由于某种原因上绘制。 如果我去到主屏幕,然后切换回活动一切如预期将会出现。 所以我搜索的方法来强制屏幕重绘,我发现以下几点:
强制全屏活动重新测量/重绘的简历?
基于对这个问题的答案我下面的代码添加到onActivityCreated()
我ListFragment的方法:
getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 0);
有了这个代码后一切正常。 但是,这仍然是一个解决方法,因此,如果有人给出了一个答案,一个更好的解决方案或解释这个问题,我会给予奖励的奖金。
这个问题可能来自getLoaderManager()
这不会回调发送到正确的地方。
如果你正在使用ActionBarSherlock那么就意味着你是在Android 2.x的吧? 你使用的是Android支持包v4的考虑? http://developer.android.com/sdk/compatibility-library.html
然后,您可以使用android.support.v4.app.ListFragment
,让你的LoaderManager
通过调用getActivity().getSupportLoaderManager()
由于您使用的是自定义的加载,你知道,如果你有同样的问题,使用本机CursorLoader什么时候? 如果没有,那么或许,你可以用Android的源比较你的装载机,看看他们正在做不同的东西吗?
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/content/CursorLoader.java
文章来源: How can I refresh my ListFragment when it returns to the layout from back stack?