我怎么能刷新我的ListFragment当它返回从后退堆栈的布局?(How can I refres

2019-07-29 15:53发布

首先,我要指出,我使用的向后兼容性的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);
}

一些注意事项:

  1. 我不能使用setListShown(true) ,因为我得到的实例方法IllegalStateException ,它不能用自定义内容视图中使用。
  2. AccountsCursorAdapter延伸SimpleCursorAdapter并修改只有bindView()方法。

Answer 1:

尤里卡! 我发现它(意外,当然)

TL; DR;

在AccountsListFragment ,我现在创建我的数据库适配器( AccountsDatabaseAdapter中) onCreate()方法,并在其关闭onDestroy()方法,它现在的作品。 以前我是我创造的适配器onActivityCreated()和关闭onDestroyView() 请注意,我不是指ListAdapter ,而是我的数据库接口AccountsDbAdapter

尝试在长的解释:

好吧,我这样做是因为我觉得通过越来越上下文getActivity()的将是不可能onCreate()方法。 事实证明,你可以getActivity()甚至在onActivityCreated()被调用。

但我真的不能解释为什么这现在工作,因为Loader有它自己的DatabaseAdapter它用来检索数据对象。 如果我猜,我会说,同一个数据库对象返回两个数据库适配器( 数据库高速缓存 )。 这意味着,当我关闭一个在onDestroyView()另一个也被关闭,光标数据集变得无效,导致一个空列表视图。 装载机不会重新加载,因为它认为该数据并没有改变。

但是,即使这种解释不符合我完全,因为这里的一些建议的解决方案,我试图像力重新加载每次没有工作。 (在loadInBackground()方法,一个新的DatabaseAdapter创建的每个时间)。

无论如何,如果你碰巧有一个更好的了解是怎么回事的,请在评论锤离开。

感谢大家与此帮助!



Answer 2:

您是否尝试迫使装载机在你的活动重新启动,基础数据集更改后?

尝试:

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


Answer 3:

尝试的forceload() :

getLoaderManager().getLoader( 0 ).forceLoad();


Answer 4:

什么适配器能看到:

为什么你看到一个空的ListView的原因是因为在返回的光标位置处于最后一个元素指向 。 当你swap()光标的适配器,适配器将尝试使用迭代while(Cursor.moveToNext())循环。 因为循环总是判断为假,你的ListView给你一个空指针的错觉。

打印的值Cursor.getCount()Cursor.getPosition()onLoadFinished() 如果我是正确的,这两个值应该是相等的。 指数的这种冲突造成上述假象。

为什么适配器看到这一点:

装载机将尽可能重新使用游标。 如果您要求的装载机一组数据并没有改变,装载机是聪明的,并返回通过onLoadFinished光标没有做任何额外的工作,甚至没有光标的位置设置为-1。

ANS呼叫Cursor.moveToPosition(-1)onLoadFinished()手动来解决这个问题。



Answer 5:

在我来说,我发现ListView控件根本没有屏幕由于某种原因上绘制。 如果我去到主屏幕,然后切换回活动一切如预期将会出现。 所以我搜索的方法来强制屏幕重绘,我发现以下几点:

强制全屏活动重新测量/重绘的简历?

基于对这个问题的答案我下面的代码添加到onActivityCreated()我ListFragment的方法:

getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 0);

有了这个代码后一切正常。 但是,这仍然是一个解决方法,因此,如果有人给出了一个答案,一个更好的解决方案或解释这个问题,我会给予奖励的奖金。



Answer 6:

这个问题可能来自getLoaderManager()这不会回调发送到正确的地方。

如果你正在使用ActionBarSherlock那么就意味着你是在Android 2.x的吧? 你使用的是Android支持包v4的考虑? http://developer.android.com/sdk/compatibility-library.html

然后,您可以使用android.support.v4.app.ListFragment ,让你的LoaderManager通过调用getActivity().getSupportLoaderManager()



Answer 7:

由于您使用的是自定义的加载,你知道,如果你有同样的问题,使用本机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?