Android Studio 开启视图绑定 viewBinding
admin
2024-05-19 09:34:13
0次

Google 在 Android Studio 3.6 Canary 11 及更高版本中提供了一个 viewBinding 的开关,可以开启视图绑定功能,以此来替代 findViewById。

viewBinding功能可按模块启用。要在某个模块中启用viewBinding,请将 viewBinding 元素添加到其 build.gradle 文件中,如下例所示:

android {...viewBinding {enabled = true}
}

如果您希望在生成绑定类时忽略某个布局文件,请将 tools:viewBindingIgnore="true" 属性添加到相应布局文件的根视图中:

...

为某个模块启用视图绑定功能后,系统会为该模块中包含的每个 XML 布局文件生成一个绑定类。每个绑定类均包含对根View以及具有 ID 的所有View的引用。系统会通过以下方式生成绑定类的名称:将 XML 文件的名称转换为驼峰式大小写,并在末尾添加“Binding”。

例如,假设某个布局文件的名称为 result_profile.xml:

所生成的绑定类的名称就为 ResultProfileBinding。此类具有两个字段:一个是名为 name 的 TextView,另一个是名为 button 的 Button。该布局中的 ImageView 没有 ID,因此绑定类中不存在对它的引用。

每个绑定类还包含一个 getRoot() 方法,用于为相应布局文件的根View提供直接引用。在此示例中,ResultProfileBinding 类中的 getRoot() 方法会返回 LinearLayout 根视图。

在 Activity 中使用 viewBinding

如需设置绑定类的实例以供 Activity 使用,请在 Activity 的 onCreate() 方法中执行以下步骤:

  1. 调用生成的绑定类中包含的静态 inflate() 方法。此操作会创建该绑定类的实例以供 Activity 使用。
  2. 通过调用 getRoot() 方法或使用 Kotlin 属性语法获取对根View的引用。
  3. 将根视图传递到 setContentView(),使其成为屏幕上的活动View。
    private lateinit var binding: ResultProfileBindingoverride fun onCreate(savedInstanceState: Bundle) {super.onCreate(savedInstanceState)binding = ResultProfileBinding.inflate(layoutInflater)val view = binding.rootsetContentView(view)}

然后即可使用该绑定类的实例来引用任何View控件:

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

在 Fragment 中使用 viewBinding

如需设置绑定类的实例以供 Fragment 使用,请在 Fragment 的 onCreateView() 方法中执行以下步骤:

  1. 调用生成的绑定类中包含的静态 inflate() 方法。此操作会创建该绑定类的实例以供 Fragment 使用。
  2. 通过调用 getRoot() 方法或使用 Kotlin 属性语法获取对根View的引用。
  3. 从 onCreateView() 方法返回根View,使其成为屏幕上的活动View。
    private var _binding: ResultProfileBinding? = null// This property is only valid between onCreateView and onDestroyView.private val binding get() = _binding!!override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {_binding = ResultProfileBinding.inflate(inflater, container, false)val view = binding.rootreturn view}override fun onDestroyView() {super.onDestroyView()_binding = null}

然后即可使用该绑定类的实例来引用任何View控件:

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

注意:inflate() 方法会要求传入LayoutInflater对象。如果布局已经inflated,则可以调用绑定类的静态 bind() 方法。 例如:

/*** View Binding example with a fragment that uses the alternate constructor for inflation and* [onViewCreated] for binding.*/
class BindFragment : Fragment(R.layout.fragment_blank) {// Scoped to the lifecycle of the fragment's view (between onCreateView and onDestroyView)private var fragmentBlankBinding: FragmentBlankBinding? = nulloverride fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)val binding = FragmentBlankBinding.bind(view)fragmentBlankBinding = bindingbinding.textViewFragment.text = getString(string.hello_from_vb_bindfragment)}override fun onDestroyView() {// Consider not storing the binding instance in a field, if not needed.fragmentBlankBinding = nullsuper.onDestroyView()}
}

注意:Fragment 的存在时间比其视图长。请务必在 Fragment 的 onDestroyView() 方法中清除对绑定类实例的所有引用。

与 findViewById 的区别

与使用 findViewById 相比,viewBinding具有一些很显著的优点:

  • Null 安全:由于viewBinding会创建对View的直接引用,因此不存在因View ID 无效而引发空指针异常的风险。此外,如果View仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用 @Nullable 标记。
  • 类型安全:每个绑定类中的字段均具有与它们在 XML 文件中引用的View相匹配的类型。这意味着不存在发生类转换异常的风险。

这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。

与 dataBinding 的对比

viewBinding和dataBinding 均会生成可用于直接引用视图的绑定类。但是,viewBinding旨在处理更简单的用例,与dataBinding 相比,具有以下优势:

  • 更快的编译速度:viewBinding不需要处理注解,因此编译时间更短。
  • 易于使用:viewBinding不需要特别标记的 XML 布局文件,因此在应用中采用速度更快。在模块中启用viewBinding后,它会自动应用于该模块的所有布局。

反过来,与 dataBinding 相比,viewBinding 也具有以下限制:

  • viewBinding不支持布局变量或布局表达式,因此不能用于直接在 XML 布局文件中声明动态界面内容。
  • viewBinding不支持双向数据绑定。

替代 KAE

viewBinding 还有一个重要作用是替代以前的 Kotlin Android Extensions,在之前的kotlin版本中提供了一个针对android的扩展插件,它可以允许我们直接用布局文件中的 view id 来访问 view,也无需写 findViewById。

但是由于 KAE 存在一些潜在的 bug (例如可以访问到不属于当前Activity布局的view id造成空指针异常等), 从 Kotlin 1.7 开始,KAE被正式移除了。

那么 viewBinding 的出现也是为了弥补之前 KAE 的功能和缺陷。


最后,viewBinding 只是针对传统 View 体系的开发,在进入 Jetpack Compose 的世界以后,这项功能就基本无用武之地了。

相关内容

热门资讯

“床车大军”只蹭厕所不住房,酒... ▲资料图:新能源汽车在某充换电站充电。多功能配置让新能源汽车成了可供休息的“床车”。图/新华社“自驾...
家国同框 | 假期里的韩家窝村 10月5日清晨,来到韩家窝村,此村坐落于淄博周村南郊镇,墨水河畔,三面环山,是省级传统古村落,国家3...
假期余额不足 成都市民近郊游享... 10月6日,距离国庆假期结束仅剩一天。成都阳光普照,在百仁公园里,草坪上满是天幕与帐篷。市民们在城区...
散客占比近八成,九寨沟迈入“散... 封面新闻记者 杨金祝九寨沟景区正进入散客时代。10月6日,记者从九寨沟景区获悉,国庆假期,九寨沟迎来...
黄金周 中国游 | “便利政策... 央视网消息:上海正全力打造“中国入境游第一站”,并推动入境游从赏景购物转向深度体验。在上海,外国游客...
通讯|布哈拉全城都知道中国放长...   新华社塔什干10月6日电 通讯|布哈拉全城都知道中国放长假了——探访中亚跨境旅游热  新华社记者...
奔县游|美食好物:小城烟火藏文...   眼下,以沉浸式、慢体验、近短途为特点的“奔县游”持续升温。地处江淮分水岭的安徽省来安县,立足半山...
专访丨约旦多措并举吸引中国游客... 新华社安曼10月6日电 专访|约旦多措并举吸引中国游客——访约旦旅游和文物大臣希贾津新华社记者何奕萍...
国庆别去外滩了,长宁才是隐藏款 国庆的上海,外滩是人山人海。但真正好逛的地方,不仅仅在最热闹的地界。长宁区延安西路1262号,上生·...
大渡河畔红色地标引游客 标题:赓续长征精神 奋进复兴征程|大渡河畔红色地标引游客国庆假期,各地游客来到位于四川省雅安市石棉县...