以这种方式重用Fragment View会导致一些问题吗?

时间:2014-05-07 14:00:53

标签: android fragment fragmentmanager

就是这种情况。我在片段A中有一个列表视图,其中包含无限列表,当用户到达底部时,该列表将通过Web服务填充。

列表视图中的每个项目都有一个"查看更多"链接打开此项目的详细片段B.

我使用FragmentManager.replace()方法和" addToBackStack"。 (我' m"替换"而不是"添加"因为我在片段A中有菜单项,我不想在片段B中显示。我已经尝试了不同的添加片段的方法,而不是在打开已经工作的片段B时删除并尝试隐藏菜单项,但在其他一些问题中结束,所以我更喜欢使用replace")

说明用户正在查看列表中的第25项,然后打开详细信息片段。当用户然后点击后退按钮时,我希望用户继续完全查看相同位置的列表。

这很容易用"添加片段"而不是"取代"因为片段从未被删除。当使用"替换"该片段被删除,然后在回击时它将再次渲染(也就是说,将再次调用onCreateView)

但此时,已经为片段创建了视图,因为FragmentManager.remove仅从视图层次结构中删除视图,但不要销毁该片段。所以我理论上"可以做这样的事情:

if(view == null){
    //Create view
    view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
}
return view;

但在这种情况下,它将导致

  

java.lang.IllegalStateException:指定的子节点已经有了   家长。您必须先在孩子的父母身上调用removeView()。

所以,我的解决方案如下:

if(view == null){
    view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
} else {
    ((ViewGroup) view.getParent()).removeView(view);
}
return view;

这对我有用,但我不知道是否会有一些"隐藏"超出此解决方案的错误,我现在没有看到。

我想听听你的意见。提前致谢

2 个答案:

答案 0 :(得分:0)

为什么不记住用户滚动的位置onPause片段并将列表视图位置设置为onResume中的滚动位置?只是一个想法,我不确定您的解决方案是否有任何不利影响/错误。

  @Override
  public void onPause() {
    // TODO Auto-generated method stub
    super.onPause();

   try{
         index = this.getListView().getFirstVisiblePosition();
         View v = this.getListView().getChildAt(0);
         top = (v == null) ? 0 : v.getTop();
      }
      catch(Throwable t){
         t.printStackTrace();
      }

在片段的onResume上:

   @Override
public void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    /**
     *  Check to see if there is any scroll position
     *  saved up, this is done in case of user returning 
     *  back from the contact detail screen
     */
    setListAdapter(adapter);
      if(index!=-1){
         this.getListView().setSelectionFromTop(index, top);
      }
}

希望这有帮助!

答案 1 :(得分:0)

如果在执行删除片段的事务时未调用addToBackStack(),则在提交事务并且用户无法导航回到该片段时,该片段将被销毁。然而,如果您在删除片段时调用addToBackStack(),则片段将停止,并且如果用户导航回来,将会恢复该片段。

  

提示:对于每个片段事务,您可以应用转换   动画,通过在提交之前调用setTransition()。

调用commit()不会立即执行事务。相反,它会在线程能够执行时将其安排在活动的UI线程(“主”线程)上运行。但是,如果需要,您可以从UI线程调用executePendingTransactions()以立即执行commit()提交的事务。除非事务是其他线程中作业的依赖项,否则通常不需要这样做。