【问题标题】:Confusion regarding inflater.inflate Android documentation关于inflater.inflate Android 文档的困惑
【发布时间】:2015-08-06 11:29:18
【问题描述】:

我正在研究这个链接的片段:http://developer.android.com/guide/components/fragments.html

有一段代码如下:

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

}

我对 attachToRoot 参数感到困惑,所以我在 Stack Overflow 上查找了一些帮助,并在类似问题上找到了很好的答案。所以我的理解是,如果您将其设置为 true,片段将附加到活动的根布局,并从那里派生其 layoutparams。如果它是假的,它将简单地返回膨胀布局的根,并像片段的独立视图一样(从传入的容器中派生布局参数)。

现在我进一步阅读了有关上述示例的 attachToRoot 文档:

一个布尔值,指示是否应将膨胀的布局附加到 膨胀期间的 ViewGroup(第二个参数)。 (在这种情况下, 这是错误的,因为系统已经在插入充气的 布局到容器中——传递 true 会创建一个冗余视图 在最终布局中分组。)

我没有得到最后一个括号声明它应该是错误的,因为我们已经将布局插入到容器中。我们已经在没有 attachToRoot 的情况下将其插入容器中是什么意思?如果参数为真,最终布局将如何具有冗余视图组。详细说明这部分的示例将有很大帮助。谢谢。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    我通常不回答自己的问题,但在对此进行了更多研究之后,我认为这可能对其他人有所帮助。虽然Marcin的回答是正确的,但我只是回答得详细一点。

    根据代码:

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

    第二个参数container是一个framelayout,id是fragment_container,activity用来添加fragment到它的布局中。

    现在,如果我们深入研究 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 为真,它会这样做:

    if (root != null && attachToRoot) {
        root.addView(temp, params);
    }
    

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

    如果 attachToRoot 为假,它会这样做:

    if (root == null || !attachToRoot) {
       result = temp;   
    }
    

    很明显,如果 attachToRoot 为真,它只是在向其添加临时视图(根视图)后返回根(fragment_container 即 id 活动用于将片段放入其中。)在本例中的 example_fragment 中))。

    如果attachToRoot为false,它只是简单的返回fragment的xml的根,即容器参数只是用来获取fragment的根视图的layoutParams(因为它没有根,所以它需要某个地方的参数)。

    如果为真,问题出现在上面的例子中,因为返回值是root(fragment_container 添加了view temp,并且fragment_container 默认已经有一个父级。)。现在,如果您尝试进行片段事务,您正在尝试将子视图 fragment_container(已经有一个父视图添加到另一个 xml(您定义的将片段添加到的框架布局)。

    因此,Android 会抛出以下异常:

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

    将其设置为 true 并返回时的问题是返回的视图已经有父视图,因此不能在其他地方使用。其他方式,您可以在 onCreateView(可能是 LinearLayout)中创建一个单独的视图组,将参数设置为 true,然后返回视图。然后它会正常工作,因为视图组不会有现有的父级。

    这是我对上述问题的理解,我可能是错的,在这种情况下我希望任何Android专家纠正这个问题。

    【讨论】:

    • 精彩的观察!
    • 谢谢!这真的很令人困惑......他们应该以一种不那么令人困惑的方式命名参数。在我看来,他们应该将参数重命名为 inflate(resource, parent, attachToParent) 而不是 inflate(resource, root, attachToRoot) ,因为后者只是含糊不清且被反复提及。
    【解决方案2】:

    这意味着如果onCreateView() 返回的View 无论如何都会附加到容器视图,因此在您的onCreateView() 中将其设置为true 会导致它被添加到容器布局中两次,这不是t 你通常想要的。并且将根视图设置为非 null 并且仍然具有 attachToRoot false 允许从根派生膨胀视图,而无需添加。

    【讨论】:

    • 嗨,Marcin,您能告诉我任何我们将其设置为 true 的情况吗?任何小例子都会有所帮助。
    • 例如,您从许多布局构建视图。然后,您可以单独为它们充气并手动执行 addView(),或者只是将这个标志设置为 true 而不再打扰。
    • @gauravjain 这都回答了你的问题吗?
    • 它部分可以,但我没有接受,因为我的同事解释了完整的解决方案,他不在 SO 上。所以,我在这里没有接受任何答案。
    • 嗯,你可以说它有点短,或者我可能需要一些时间来掌握这些东西。当我看到源代码时,我真的可以了解幕后发生的事情,以及当该参数为真时导致最终布局中出现冗余和异常的原因。但是,是的,正如我所说,我很欣赏你的回答,因为在 Elitz 写下他的答案之前,这是唯一合法的答案。另外,感谢上面的链接,但这并不是说我不接受任何问题的答案。
    【解决方案3】:

    检查一下

    View v =getLayoutInflater.inflate(R.layout.example_fragment, viewgroup);
    

    还有这个

    View v =getLayoutInflater.inflate(R.layout.example_fragment, null);
    

    如果你在第一个场景中调用它

    Log.v("testing",String.valueOf(v.getParent() == null));
    

    你会得到false作为输出,但是当你检查第二行时你会得到true

    简单的理解是,如果你指定一个父级(ViewGroup)它附加到它,但是如果你添加最后一个参数,你告诉充气器跳过视图的附件,所以你返回的视图没有父级,但是如果你指定null,谁会被附上? NOBODY 所以返回的 View 没有父级,并且像您所说的那样,它为 View 派生 layoutParameters。

    如果您不添加最后一个参数,则 View 将其父级作为 Activity View,因此在添加之前将在您的 OncreateView 中返回,这将导致一些异常,因为 View 不能有不同的爸爸,片段将无法管理视图本身。

    如果添加 true,则从您的 oncreateView 中返回 null

    【讨论】:

      【解决方案4】:

      从片段的 onCreateView() 方法返回的视图,将被系统附加到片段的容器中。所以在这种情况下,inflate() 方法的第三个参数应该是 false。如果将其设置为 true,那么它将被附加到根目录两次。所以在这种情况下你应该把它设置为 false。

      现在,膨胀视图从 inflate() 方法的第二个参数而不是第三个布尔参数派生其布局参数。

      【讨论】:

        【解决方案5】:

        好的,来自android官方文档Android documentation

        什么是片段?

        Fragment 表示 Activity 中的一种行为或用户界面的一部分。您可以在单个活动中组合多个片段以构建多窗格 UI 并在多个活动中重用一个片段。您可以将片段视为活动的模块化部分,它有自己的生命周期,接收自己的输入事件,并且可以在活动运行时添加或删除(有点像“子活动”,您可以在不同的活动中重复使用)。

        如何在Activity中使用Fragment?

        片段必须始终嵌入到活动中,并且片段的生命周期直接受宿主活动生命周期的影响。比如当activity暂停时,里面的所有fragment都会暂停,当activity销毁时,所有fragment也会暂停。但是,当一个 Activity 运行时(它处于恢复的生命周期状态),您可以独立地操作每个 Fragment,例如添加或删除它们。

        什么是分片交易

        您可以独立操作每个片段,例如添加或删除它们。当您执行这样的片段事务时,您还可以将其添加到由 Activity 管理的回退堆栈中 - 活动中的每个回退堆栈条目都是发生的片段事务的记录。后退堆栈允许用户通过按“后退”按钮来撤销片段事务(向后导航)。

        片段和活动如何相互作用

        当您将片段添加为 Activity 布局的一部分时,它位于 Activity 视图层次结构内的 ViewGroup 中,并且片段定义了自己的视图布局。您可以通过在 Activity 的布局文件中将片段声明为元素,或通过将片段添加到现有 ViewGroup 来从应用程序代码中将片段插入到您的 Activity 布局中。

        片段生命周期方法 onCreateView() onCreate() onPause()

        你的问题是

        我们已经在没有 attachToRoot 为 true 的情况下插入到容器中是什么意思?如果参数为真,最终布局怎么会有多余的视图组

        这里是答案 假设您已经在活动布局中添加了,那么您不需要将最后一个参数设置为 true。因为每次执行片段的添加或删除时,它们都是片段事务。 但是,如果您尚未在布局中添加片段,则可以将其设置为 true。

        在文档中阅读此内容

        您可以通过在 Activity 的布局文件中将片段声明为元素,或者通过将片段添加到现有 ViewGroup 来从应用程序代码中将片段插入到您的 Activity 布局中。但是,片段不需要成为活动布局的一部分;您也可以使用没有自己 UI 的片段作为 Activity 的隐形工作者。

        所有片段事务都添加到活动回栈

        【讨论】:

        • 我想你不太明白我的问题。它与我如何将片段添加到活动(静态或动态)无关。很清楚,问题出在 attachToRoot 参数中。根据您对动态添加片段到活动的回答,我们应该将其设置为 true,这不太正确(它会引发异常)。无论如何,我感谢您的努力和时间。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-11
        • 1970-01-01
        • 2017-10-26
        • 2019-05-17
        • 2020-03-06
        • 2016-03-16
        • 2013-07-27
        相关资源
        最近更新 更多