android-fragments 片段-我应该在onCreateView中重用视图吗?我应该怎么做?

z0qdvdin  于 2022-11-13  发布在  Android
关注(0)|答案(3)|浏览(136)

实际上,我总是在我的片段中重复使用我的观点,如下所示:

private View mView = null;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    if (mView == null)
        mView = inflater.inflate(R.layout.view);
    return mView;
}

现在我也开始在简单的活动中使用我的片段,如果,也只有如果,我将片段添加到backstack,这将因为java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.而失败
所以我的问题是:

  • 如果我选中视图的父视图,删除它并将其添加到新的父视图中,是否可以?
  • 或者我应该总是重新创建视图而从不重用它吗?如果是,为什么?
  • 是否存在重用视图将失败的其他点?
gkn4icbw

gkn4icbw1#

我知道这是一个老问题。但是在使用片段几个月后,我发现在使用缓存时需要注意的一点是:如果你当前缓存的布局还有另外一个fragment标签,这种缓存策略会导致嵌入的fragment丢失一些生命周期回调。
1.当前片段onCreateView是第一次调用。通过如上所述的缓存,我们将扩大目标布局(此布局包括片段标记)。
1.通过inflater.inflate这将使嵌入片段正确地添加到布局中,onCreateView将被调用。
1.当需要销毁当前片段时,将正确调用嵌入片段onDestroyView
1.当当前片段onCreateView被再次调用时,我们返回一个缓存的视图,而不调用inflater.inflate。你会发现嵌入片段onCreateViewonDestroyView或其他生命周期方法不会被调用。
这就是我想说的。

pcww981p

pcww981p2#

也许这可以帮助你理解这种行为。如果你查看FragmentManagerImpl.java,你会发现以下内容:
首先,我们通过调用onCreateView()创建一个视图(* 第845行 ),然后我们用另一个视图 Package 创建的视图,该视图将成为我们视图的父视图( 848-849行 *)这意味着我们的视图不会成为真实的容器的子视图,但它现在是 Package 器视图的子视图。FragmentManager从容器中删除了 Package 器视图,但是我们的真实的视图仍然添加到父 Package 器视图中。这就是您遇到的问题的原因。
因此,如果你从它的父视图中删除视图,它就可以工作。即使知道这一点,我也不建议在片段中重用视图,因为视图的寿命可能比片段长一点,因为即使片段被破坏后,它们也可以用于“消失”的动画。如果你试图在那时从它的父视图中删除这样的视图,那么动画可能会被破坏。
不缓存视图的另一个理由是,Android在设计上不支持片段中的视图回收。还记得ListAdapter允许重用视图吗?Android负责缓存和正确重用这些视图。但片段不是这样。

6ljaweal

6ljaweal3#

我目前正在重用该视图,如下所示:

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

我不知道这种方法是否正确,但它似乎对我有用。
注意:我使用这个方法是因为我在片段中有一个列表视图,当用户点击一个项目时,它会加载一个新的片段(片段管理器使用替换当前列表片段)。然后,当用户点击后退按钮时,因为我在重用相同的旧片段视图(使用FM删除时不会破坏),所以用户会继续在打开详细片段视图之前的位置查看列表。

相关问题