片段 - 我应该在 onCreateView 中重用视图,我应该怎么做?
Posted
技术标签:
【中文标题】片段 - 我应该在 onCreateView 中重用视图,我应该怎么做?【英文标题】:Fragment - should I reuse view in onCreateView and how should I do that? 【发布时间】:2013-09-09 08:03:11 【问题描述】:实际上,我总是在片段中重复使用我的视图,如下所示:
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;
使用 viewpager 等有效。现在我也开始在简单的活动中使用我的片段,当且仅当我将片段添加到后台堆栈时,这将失败,因为java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
所以我的问题是:
可以吗,如果我检查视图父级,将其删除并添加到新父级? 或者我应该总是重新创建视图并且从不重复使用它?如果是,为什么? 是否还有其他点会导致重用视图失败?【问题讨论】:
【参考方案1】:也许这有助于理解行为。如果您查看FragmentManagerImpl.java,您会发现以下内容:
首先我们通过调用onCreateView()
(第 845 行)创建一个视图,然后我们用另一个视图包装创建的视图,它成为我们视图的父视图(第 848-849 行)。这意味着我们的视图不会成为真正容器的子视图,但它现在是包装视图的子视图。当视图从容器中移除时(第 998 行),重用问题就会发生。 FragmentManager 从容器中移除包装视图,但我们的真实视图仍然添加到父包装视图。这就是导致您遇到问题的原因。
因此,如果您将视图从其父视图中移除,它就可以工作。即使知道这一点,我也不建议在片段中重用视图,因为视图可以比片段更长寿,因为即使在片段被销毁后它们也可以用于“消失”动画。如果您当时尝试从其父视图中移除此类视图,则动画可能会被破坏。
另一个不缓存视图的论据是,android 不支持在设计上在片段中回收视图。还记得ListAdapter
允许重用视图吗? Android 负责缓存和正确重用这些视图。但片段并非如此。
【讨论】:
【参考方案2】:我目前正在重用视图,如下所示:
if(view == null)
view = (ViewGroup) inflater.inflate(R.layout.news_list, container, false);
else
((ViewGroup) view.getParent()).removeView(view);
return view;
我不知道这种方式是否正确,但它似乎对我有用..
注意:我使用这种方法是因为我在片段中有一个列表视图,当用户点击一个项目时,它会加载一个新片段(片段管理器使用当前列表片段替换)。然后,当用户点击后退按钮时,因为我正在重用片段的相同旧视图(使用 FM 删除时不会破坏),然后用户继续在打开详细片段视图之前的位置查看列表。
【讨论】:
嗨@edrain,您的解决方案工作正常,但即使我弹出了我的片段,它也没有从容器中删除视图。【参考方案3】:我知道这是一个老问题。但是在使用 Fragment 几个月后,我发现在这种方式使用缓存时需要提到的一点是:如果您当前缓存的布局还有另一个 Fragment 标签,这种缓存策略会导致嵌入 Fragment 丢失一些生命周期回调。我会详细说:
1.当前片段onCreateView
被第一次调用。通过像上面这样的缓存,我们将膨胀目标布局(这个布局包括一个片段标签)。
2.通过inflater.inflate
这将使嵌入片段正确添加到布局中,onCreateView
将被调用。
3.当前fragment需要销毁时,embed fragmentonDestroyView
会被正确调用。
4.当当前片段onCreateView
再次调用时,我们返回一个缓存视图,而不调用inflater.inflate
。您会发现嵌入片段onCreateView
和onDestroyView
或其他生命周期方法不会被调用。
这就是我想说的。
【讨论】:
以上是关于片段 - 我应该在 onCreateView 中重用视图,我应该怎么做?的主要内容,如果未能解决你的问题,请参考以下文章
Android Java:在 onCreateView() 中返回空视图的片段
替换未调用 onAttach、onCreate、onCreateView 等的活动中的片段