该 生成的绑定类 中的数据绑定库有不同版本的 inflate
的方法。一个看起来像通常的 LayoutInflater.inflate
方法,该方法以 viewGroup
和 attachToRoot
参数,而一个只需要一个 LayoutInflater
而不是其他。
文档并没有解释两者之间的区别,而且不幸的是,Android Studio并没有让我通过源代码的 inflate
这样我就可以弄清楚它内部使用的是哪些值来做为 viewGroup
和 attachToRoot
. 当在屏幕上放置碎片时,我注意到两者之间没有区别。当我用它来处理RecyclerView项目时,我发现 inflate
方法,只需要一个 LayoutInflater
不正确地放置项目。
所以我的问题是:对于 viewGroup
和 attachToRoot
此方法是否在内部使用,是否适合在片段的 onCreateView
?
这个方法内部使用了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
, 它被委托给布局管理器. 现在看看默认的 LayoutParams
由 LinearLayoutManager
:
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
通常情况下,如果您计划使用垂直列表,您将设置为 android:layout_width="match_parent"
的项目上。但是当你附加一个没有 LayoutParams
到 RecyclerView
,它得到的两个尺寸都设置为 wrap_content
. 这就是为什么你的布局看起来不对的原因,当充气与 root == null
.
使用[单参数]是否合适?
inflate
方法]在片段的onCreateView
?
单参数的膨胀器可以用于膨胀对话框视图,在这里没有父容器根视图。
通常情况下,你会将一个片段附加到一个叫做 FrameLayout
或 FragmentContainerView
延伸 FrameLayout
). FrameLayout
产生 LayoutParams
与 match_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()
}
如果你正在使用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。null
和 false
是默认值传递给你的,当你这样做的时候。
val binding: MyFragmentBinding = MyFragmentBinding.inflate(inflater)
它是类似于做。
val binding: MyFragmentBinding = MyFragmentBinding.inflate(inflater, null, false)