如何保存具有列表视图的片段状态

Posted

技术标签:

【中文标题】如何保存具有列表视图的片段状态【英文标题】:How to save state of Fragment having listview 【发布时间】:2013-07-22 13:20:28 【问题描述】:

这是一种情况。我想从 Fragment A-> B-> C 导航。

在 B 片段中有列表视图。在项目上单击我打开详细视图 C 片段。 当然,我使用了替换方法并在从 B 到 C 的事务时添加了 addtoBackStack(null),以便在返回时它返回到 B。

一切顺利。但是当我从 C 返回到 B 时,视图正在刷新,因此再次调用 web 服务。我不想这样做。我想用listview保留B Fragment状态。

我收到了一些 Retain Instance 的帖子,但没有太大帮助。

非常感谢任何帮助。

谢谢。

【问题讨论】:

您是否考虑过使用Bundle 和覆盖onSavedInstance() 嗨@dakshbhatt21,你的问题找到解决方案了吗?我也有同样的问题,困扰了我一个星期,没有任何突破。 嗨@mungaihkamau请查看这篇文章developer.android.com/training/implementing-navigation/…,您可以在使用片段时找到各种类型的导航,请查看并告诉我。 【参考方案1】:

正如here 解释的那样,您可以使用 onSaveInstanceState() 将数据保存在 Bundle 中,并在 onRestoreInstanceState() 方法中检索该数据。

setRetainState(true) 经常被提到作为在片段中保持 ui 状态的方法,但它对你不起作用,因为你正在使用 backstack。

因此,您可以将滚动位置保存在 onSaveInstanceState() 中并在 onRestoreInstanceState() 中恢复它,如下所示:

public class MyListFragment extends ListFragment 

@Override
public void onSaveInstanceState(Bundle outState) 
    super.onSaveInstanceState(outState);

     int index = this.getListView().getFirstVisiblePosition();
     View v = this.getListView().getChildAt(0);
     int top = (v == null) ? 0 : v.getTop();

     outState.putInt("index", index);
     outState.putInt("top", top);


@Override
public void onActivityCreated(Bundle savedInstanceState) 
    super.onActivityCreated(savedInstanceState);
    [...]
    if (savedInstanceState != null) 
        // Restore last state for checked position.
        index = savedInstanceState.getInt("index", -1);
        top = savedInstanceState.getInt("top", 0);
    
    if(index!=-1)
     this.getListView().setSelectionFromTop(index, top);
  


您可以找到更详细的类似示例here。

【讨论】:

@alex 这对我不起作用。我在搜索按钮(底部栏按钮)中有列表视图。当我点击下面的搜索按钮时,我的列表视图将被重新创建。我无法保存列表视图的状态。帮帮我.. 能否请您发布您的 xml 布局并显示您的代码。最好开始一个新问题,这样做并将这个问题线程链接为“相似”【参考方案2】:

我通过在 onCreate() 而不是 onCreateView() 上创建适配器解决了这个问题。

这是因为(我认为)添加到 backstack 的片段丢失了它的视图,然后它必须重新创建视图。 onCreateView() 被调用并顺便重新创建您的适配器。

【讨论】:

【参考方案3】:

您可以在 oncreate 中保存定义您的用户界面。 在 onCreateView 中时,仅将其添加到布局中。 所以视图状态可以完美保存。

这是我的 sv:

在创建时

 LayoutInflater inflater = (LayoutInflater)
            ctx.getSystemService(ctx.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(R.layout.pulltorefreshgridview, null);
    mPullRefreshGridView = (PullToRefreshGridView) view
            .findViewById(R.id.listcate_pullrefresh_gridview);

强文本 在 onCreateView 中

if (rootView != null) ((LinearLayout)rootView).removeAllViews();
View v = inflater.inflate(R.layout.listcate_fragment, container, false);
rootView = v;


    ((LinearLayout) v).addView(mPullRefreshGridView,
            new LinearLayout.LayoutParams(
                    LinearLayout.LayoutParams.FILL_PARENT,
                    LinearLayout.LayoutParams.FILL_PARENT));

【讨论】:

【参考方案4】:

我认为您可以在离开片段 B 之前保存 ListView 的位置。 也许在片段 B 的 onStop() 中这样做。当您返回时,您可以获取该位置并将其恢复到 ListView,例如在片段 B 的 onStart() 中执行此操作。 位置数据可能会保存在 Activity 中,因此即使 Fragment 分离也不会丢失。

需要注意的一点(我被这个困住了),如果保存的位置数据被后台服务更新,你应该避免在生命周期阶段之前将其恢复到ListView onStart() 片段B,因为实际上框架会在离开片段之前保存视图的状态,并在返回时恢复它。因此,如果您在框架执行此操作之前恢复您的位置,那么框架的恢复数据将覆盖您的。

【讨论】:

以上是关于如何保存具有列表视图的片段状态的主要内容,如果未能解决你的问题,请参考以下文章

如何使用来自另一个视图控制器swift的用户输入创建具有表视图单元格的列表

如何将可扩展列表视图的选定子视图数据从片段发送到父活动?

如何使用列表视图在选项卡式活动的片段中呈现 SQLite 表数据 [重复]

方向/配置更改后如何维护 ListView 片段状态?

单例片段或保存网页视图状态

如何将列表视图中的数据从一个片段发送到另一个片段