Kotlin|Kotlin Android Extensions遭废弃,官方推荐使用ViewBinding

Kotlin|Kotlin Android Extensions遭废弃,官方推荐使用ViewBinding
文章图片

https://youtrack.jetbrains.com/issue/KT-42121
As the @Parcelize functionality is extracted (KT-42120), the rest of the Android Extensions functionality can be deprecated in favour of View Binding.
The existing Android Extensions plugin will continue to work, however, a warning message will be shown.
记得曾经在《谁才是ButterKnife的终结者?》一文中大胆猜测ViewBinding将替代KAE,果然被不幸言中,近期KAE被正式废弃。


KAE的问题 KAE被废弃是因为存在以下几方面问题:
  • 类型安全:res下的任何id都可以被访问,有可能因访问了非当前Layout下的id而出错
  • 空安全:这主要体现在Configuration中的对应布局不全时,运行时可能出现NPE
  • 兼容性:只能在kotlin中使用,java不友好
  • 局限性:不能跨module使用
KAE被废的同时官方也给出了解决方案:迁移至ViewBinding。因为ViewBinding解决了KAE的主要缺陷:Null safety 与 Type safety,安全性更高。

ViewBinding的基本使用 开启ViewBinding很简单,只需在build.gradle中增加一下配置
android { ... buildFeatures { viewBinding true } }

ViewBinding会在编译期根据layout文件生成对应的class

针对上面activity_main.xml,会生成ActivityMainBinding的class,
public final class ActivityMainBinding implements ViewBinding { @NonNull public final TextView name; @NonNull public final Button btn; @NonNull public View getRoot() {} }

两个成员namebtn,分别对应layout中的TextView和Button。getRoot()方法返回layout的跟节点,上例中即LinearLayout
...

通过tools:viewBindingIgnore="true" 可以禁止ViewBinding的生成,所以class中没有ImageView对应的成员
在Activity中创建ViewBinding实例
private lateinit var binding: ActivityMainBindingoverride fun onCreate (savedInstanceState: Bundle?) { super.onCreate (savedInstanceState) binding = ActivityMainBinding.inflate (layoutInflater) val view = binding.root setContentView (view) }

并在适当的时候访问其成员
binding.name.text = viewModel.name binding.btn.setOnClickListener {viewModel.userClicked ()}


Fragment中的使用 【Kotlin|Kotlin Android Extensions遭废弃,官方推荐使用ViewBinding】可以在Fragment的onCreateView中创建binding,然后在onDestroyView中销毁
override fun onCreateView ( inflater: LayoutInflater, container: ViewGroup ?, savedInstanceState: Bundle? ): View? { _binding = ActivityMainBinding.inflate (inflater, container, false) val view = binding.root return view }override fun onDestroyView () { super.onDestroyView () _binding = null }

    推荐阅读