): View {
_binding = ResultProfileBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.tvHelloWorld.text = “Hello Android!”
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
还有在 Adapter 的使用,因为布局不是只创建一次,而是每有一项数据就会创建,不能像上面那样在 Adapter 里写一个 binding 全局变量,这样 binding 只会得到最后一次创建的视图。所以 binding 对象应该是给 ViewHolder 持有。
class TextAdapter(
private val list: List
) : RecyclerView.Adapter<TextAdapter.TextViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextViewHolder {
val binding = ItemTextBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return TextViewHolder(binding)
}
override fun onBindViewHolder(holder: TextViewHolder, position: Int) {
val content = list[position]
holder.binding.tvContent.text = content
}
override fun getItemCount() = list.size
class TextViewHolder(val binding : ItemTextBinding) : RecyclerView.ViewHolder(binding.root)
}
常见的情况就讲完了,总结一下 ViewBinding 的用法是,获取绑定对象,然后用 getRoot() 方法拿到根视图来替代使用到布局的地方。后面就可以通过绑定对象获取布局上的控件对象。
一些使用 Java 的朋友可能会看不太懂上面的代码。这木有关系,因为不推荐直接用,模板代码用 Java 写起来更长。把上面文字看了,代码理解个大概,能比较清楚 ViewBinding 的用法就行了,接下来就是讲怎么封装来使用比较好。
ViewBinding 的封装建议
用惯了 Kotlin synthetic 用 id 获取控件,再看 ViewBinding 的用法多少会觉得有点繁琐,所以需要封装一下了,毕竟 ViewBinding 能减少 id 写错或类型写错导致的异常,而且前者快弃用了。个人想到了两种封装思路。
不依托于基类
类似在 Kotlin 使用 ViewModel 的用法,做到声明了对象即可使用,不用管是怎么创建的,不用考虑什么时候要清除实例,不用每次去写 inflate 的模板代码。这种用法的好处是想用就用,无需继承什么基类,泛用性更强,移植代码更加容易。会用到一些 Kotlin 的特性,不适用于 Java。Java 的推荐用法还在后面。
先来分析一下,首先肯定要调用 inflate() 方法,不然怎么实例化 binding 对象。但是我们可以做到使用前自动 inflate(),无需手动调用。这就用到延时委托来实现,在 Fragment 因为要清除实例后面另说。然后就是 inflate()