为什么我们需要在Android中为布局和attachToRoot充气?

时间:2018-04-21 10:16:01

标签: java android xml kotlin

我得到了这段代码:

override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater!!.inflate(R.layout.fragment_wednesday, container, false)
    }

我不明白为什么我们需要对布局进行膨胀并写入attachToRoot值。 顺便说一下,为什么我们需要一个viewGroup?

2 个答案:

答案 0 :(得分:1)

布局定义只是一些XML数据,但要真正显示布局,必须将其转换为对象树。 inflater就是这样做的。

需要一个容器(ILayoutContainer)来控制放置子树的位置(在较大的视图对象树中)。

答案 1 :(得分:0)

考虑这段代码

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup fragment_container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.example_fragment, fragment_container, false);
}

第二个参数fragment_container是一个容器(framelayout),其id为fragment_container,activity用于在其布局中添加片段视图。

没有,如果我们读取LayoutInflater类的inflate方法的源代码,我们得到这个(我删除了不必要的狗屎,让你更好地理解代码)

// The view that would be returned from this method.
View result = root;

// Temp is the root view that was found in the xml.                     
final View temp = createViewFromTag(root, name, attrs, false);

首先,它从提供的根创建一个临时视图。

如果attachToRoot为false,则执行以下操作:

// Decide whether to return the root that was passed in or the
// top view found in xml.
   if (root == null || !attachToRoot) {
         result = temp;
     }

如果attachToRoot为false,它只返回片段的xml的根,即容器参数仅用于获取片段根视图的layoutParams(因为它没有root,所以它需要来自某处的params)

如果attachToRoot为true,则执行以下操作:

 // We are supposed to attach all the views we found (int temp)
 // to root. Do that now.
  if (root != null && attachToRoot) {
           root.addView(temp, params);
    }

它将上面创建的临时视图添加到根视图(即容器)。

“第三”参数attachToRoot为true或false的主要区别在于。

true :将子视图添加到父级RIGHT

false :将子视图添加到父级NOT NOW。稍后再添加。 `

以后是什么时候?

稍后您使用例如parent.addView(childView)

一个常见的误解是,如果attachToRoot参数为false,则子视图不会添加到父视图中。的 WRONG 在这两种情况下,子视图都将添加到parentView。这只是时间的问题。

inflater.inflate(child,parent,false);
parent.addView(child); 

相当于

inflater.inflate(child,parent,true);

注意!!注意 !!注意!!

如果您不负责将子视图添加到父级,则不应将attachToRoot传递为true。

例如,添加片段时

  public View onCreateView(LayoutInflater inflater,ViewGroup parent,Bundle bundle)
  {
        super.onCreateView(inflater,parent,bundle);
        View v = inflater.inflate(R.layout.image_fragment,parent,false);
       return v;
  }

现在,如果您将第三个参数传递为true,则会因为以下代码而获得IllegalStateException。

getSupportFragmentManager()
  .beginTransaction()
  .add(parent, childFragment)
  .commit();

由于您已经错误地在onCreateView()中添加了子片段。调用add将告诉您子视图已添加到父级,因此IllegalStateException。此异常来自以下代码,可在检查LayoutInflater类中的inflate方法时找到该代码

if (child.getParent() != null) {
        throw new IllegalStateException("The specified child already has a parent. " +
                "You must call removeView() on the child's parent first.");
    }

这里你不负责添加childView,FragmentManager负责。所以在这种情况下总是传递假的