生成的绑定类,只接受一个LayoutInflater作为唯一的参数。

问题描述 投票:0回答:1

生成的绑定类 中的数据绑定库有不同版本的 inflate 的方法。一个看起来像通常的 LayoutInflater.inflate 方法,该方法以 viewGroupattachToRoot 参数,而一个只需要一个 LayoutInflater 而不是其他。

enter image description here

文档并没有解释两者之间的区别,而且不幸的是,Android Studio并没有让我通过源代码的 inflate 这样我就可以弄清楚它内部使用的是哪些值来做为 viewGroupattachToRoot. 当在屏幕上放置碎片时,我注意到两者之间没有区别。当我用它来处理RecyclerView项目时,我发现 inflate 方法,只需要一个 LayoutInflater 不正确地放置项目。

所以我的问题是:对于 viewGroupattachToRoot 此方法是否在内部使用,是否适合在片段的 onCreateView?

android android-layout android-fragments data-binding android-databinding
1个回答
1
投票

这个方法内部使用了viewGroup和attachToRoot的什么值?

这些参数镜像在 LayoutInflater 哪儿 root: ViewGroup 被描述为

可选的视图作为生成的层次结构的父级(如果 attachToRoot 为真),否则只需 一个对象,它为返回的层次结构的根提供了一组LayoutParams值。 (如果 attachToRoot 为false。) 这个值可以是 null.

来源:LayoutInflater docs。LayoutInflater docs重点是我的。

root 参数用于 产生 LayoutParams 来自 layout_* 膨胀视图的XML属性。每个布局可能理解不同的布局属性集,并定义不同的默认值集。这就是为什么您应该总是通过 root. 唯一不可能的地方是在膨胀对话框视图的时候。

绑定上的单参数方法没有提供一个 root 布局,所以没有 LayoutParams 此时会生成膨胀视图。换句话说。inflate(inflater) == inflate(inflater, null, false).

如果一个视图没有 LayoutParams 粘贴时它的新父版图将使用 generateDefaultLayoutParams.

如果你按照 generateDefaultLayoutParams 确实 RecyclerView, 它被委托给布局管理器. 现在看看默认的 LayoutParamsLinearLayoutManager:

@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
    return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
}

通常情况下,如果您计划使用垂直列表,您将设置为 android:layout_width="match_parent" 的项目上。但是当你附加一个没有 LayoutParamsRecyclerView,它得到的两个尺寸都设置为 wrap_content. 这就是为什么你的布局看起来不对的原因,当充气与 root == null.


使用[单参数]是否合适?inflate 方法]在片段的 onCreateView?

单参数的膨胀器可以用于膨胀对话框视图,在这里没有父容器根视图。

通常情况下,你会将一个片段附加到一个叫做 FrameLayoutFragmentContainerView 延伸 FrameLayout). FrameLayout 产生 LayoutParamsmatch_parent 的宽度和高度。如果您的片段没有问题,您可以使用单参数的 inflate 方法。

否则,总是使用所提供的known父代方法来生成合适的 LaoyutParams. 不要依赖默认的 LayoutParams 提供的,即使它是相同的布局。你在XML中定义了一些布局参数,你会希望它们被尊重。

记住,如果你持有对绑定的引用,就会涉及到一些片段的生命周期仪式。

这是我目前使用碎片+视图绑定的设置。

// Nullable reference so we can use it later and clear it later.
private var binding: ExampleFragmentBinding? = null

private fun requireBinding() = checkNotNull(binding)

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
    // Respect the XML layout params.
    val binding = ExampleFragmentBinding.inflate(inflater, container, false)
    this.binding = binding
    return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    val binding = requireBinding()
    // Do stuff with the views.
}

override fun onDestroyView() {
    // Detach view hierarchy reference from fragment, which may prevent memory leaks.
    this.binding = null

    super.onDestroyView()
}

0
投票

如果你正在使用Kotlin,只有在以下情况下才能使用这个版本: layoutId 是事先未知的。

private lateinit var viewModel: MyViewModel

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val binding : MyFragmentBinding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false)
    viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
    binding.myViewModel = viewModel
    binding.lifecycleOwner = this
    return binding.root
}

否则使用生成的 Binding 类的 inflate方法。

lateinit var binding: MyFragmentBinding 
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val binding = MyFragmentBinding.inflate(inflater, container, false)
    return binding.root
}

Update:

所以我的问题是:这个方法内部对viewGroup和attachToRoot使用了什么值,在片段的onCreateView中使用它是否合适?

当你调用 inflate 只有 inflater 作为paramter。nullfalse 是默认值传递给你的,当你这样做的时候。

val binding: MyFragmentBinding = MyFragmentBinding.inflate(inflater)

它是类似于做。

 val binding: MyFragmentBinding = MyFragmentBinding.inflate(inflater, null, false)
© www.soinside.com 2019 - 2024. All rights reserved.