片段 - 获取视图在调用 onCreateView 时已经有父错误

Fragment - Getting view already has a parent error on calling onCreateView

我在运行时从 activity 中扩充一个片段。所以,为了在片段 class 中膨胀片段的视图,我调用了:

  @Nullable
  @Override
  public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    return inflater.inflate(R.layout.confirm_fragment, container);
  }

此时我遇到日志崩溃:

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

但是如果我将我的方法修改为:

      @Nullable
      @Override
      public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        return inflater.inflate(R.layout.confirm_fragment, null);
      }

我现在将我的容器指定为 null,它可以工作。但是我不明白的是我在崩溃的代码中在哪里为视图指定了父级?

您需要将 attachToParent 设置为 false
示例:

inflater.inflate(R.layout.confirm_fragment, container,false);

尝试使用以下代码:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view=inflater.inflate(R.layout.confirm_fragment, container, false);
    return view;
}

where did I specify a parent for the view [...] ?

你通过写这样的东西动态地添加一个Fragment:

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.add(android.R.id.content, myFragment, FRAGMENT_TAG)
                    .addToBackStack(null)
                    .commit();

add() 中,您可以通过传递所需容器的 ID 来指定 Fragment 的显示位置(在本例中为全屏)。

另见参考文献中的方法说明developers.android.com:

containerViewId int: Optional identifier of the container this fragment is to be placed in. If 0, it will not be placed in a container.

如果您不将 Fragment 添加到 UI(例如,您需要将其作为保留片段用于缓存目的),则永远不会调用 onCreateView()

所以一旦 onCreateView() 被调用,这个 Fragment 的父级已经存在 - FragmentManager 为你设置它。

this link 中了解到为什么以及何时在 attachToRoot 参数中传递父容器的实例或 null。

来自 link:

Button button = (Button) inflater.inflate(R.layout.custom_button, mLinearLayout, false);
mLinearLayout.addView(button);

By passing in false, we say that we do not want to attach our View to the root ViewGroup just yet. We are saying that it will happen at some other point in time. In this example, the other point in time is simply the addView() method used immediately below inflation.

所以如果你用以下方法充气:

return inflater.inflate(R.layout.confirm_fragment, container);

首先它会立即将 confirm_fragment 附加到容器。返回视图后,fragment 将尝试再次隐式添加到 parent,但由于已经添加,将抛出异常:

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

希望你明白了。