前言
原始方式
在我们的开发过程中,需要获取XML布局文件中的ViewId,以便其赋值显示,我们习惯使用findViewById进行操作,可这样会导致很多的模版代码出现。
Butter Knife框架
直到Android大神 Jake Wharton开源了Butter Knife框架,通过Bind方式绑定获取ViewId。
基于Kotlin的扩展
近几年Android对Kotlin的支持,我们开始使用 Android Kotlin extensions。
在文件中导入布局文件直接引用viewId。无需做其他额外操作,最为方便。
生成代码的方式
谷歌在 Android Studio 3.6 Canary 11 及更高版本中加入了新的视图绑定方式ViewBinding。
注意:
要使用ViewBinding功能,AndroidStudio至少要升级到3.6。
ViewBinding和Kotlin扩展
ViewBinding
和 Kotlin 扩展
都是 Android 开发中常用的技术,用于简化视图查找和绑定的过程。
以下是它们之间的一些比较:
ViewBinding:
ViewBinding
是由 Android 官方推荐和支持的库,从 Android Studio 3.6 版本开始引入。ViewBinding
使用了编译时生成的绑定类,在xml
布局文件中的每个视图都会生成一个对应的绑定类对象,因此在编译时检测到视图名称的错误。ViewBinding
可以生成类型安全的代码,避免了手动查找和强制转换视图对象的麻烦。ViewBinding
不会增加 APK 大小,因为它只是编译时生成的代码。- 在多个模块中引用同一个视图时可能会出现命名冲突的问题,需要通过手动指定全限定名解决。
Kotlin扩展:
Kotlin扩展
是 Kotlin 语言的特性,其通过扩展函数的方式,允许开发者为现有的类添加新的函数或属性。Kotlin扩展
使用起来相对简单,可以直接在布局文件中使用 Kotlin 扩展函数来查找和操作视图。Kotlin扩展
对视图的数据获取和类型安全性没有提供直接的支持,需要手动处理可能的空指针异常和类型转换。Kotlin扩展
会增加 APK 的大小,因为它是在运行时动态添加的函数。
总体而言
ViewBinding
在类型安全性和编译时错误检测方面比Kotlin扩展
更好。它是官方推荐的方式,并且可以避免一些潜在的运行时异常。
但是,如果你已经熟悉并且喜欢使用
Kotlin 扩展
,并且对 APK 大小没有严格要求,那么你可以选择使用它。
ViewBinding
原理就是
Google在那个用来编译的gradle插件中增加了新功能,当某个module开启ViewBinding功能后,编译的时候就去扫描此模块下的layout文件,生成对应的binding类。
开启
KTS方式配置
build.gradle.kts中添加
1 | android { |
注意
只要开启后,会自动遍历layout下的xml文件自动生成对应的类。
使用
页面中使用
1 | private lateinit var binding: ActivityTexBinding |
原来的
1 | setContentView(R.layout.activity_tex) |
替换为
1 | binding = ActivityTexBinding.inflate(layoutInflater) |
使用
1 | val text = "$$ c = \\pm\\sqrt{a^2 + b^2} $$" |
完整代码
1 | import android.os.Bundle |
注意
ActivityTexBinding
是自动生成的类,它会自动遍历layout下的xml文件自动生成对应的类。比如我的XML是
activity_tex.xml
,它自动生成的类就是ActivityTexBinding
。如果想在生成绑定类时忽略某个布局文件,将tools:viewBindingIgnore=”true”`属性添加到相应布局文件的根视图中。
基类
Activity
1 | abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() { |
使用
1 | class MainActivity : BaseActivity<ActivityMainBinding>() { |
Fragment
1 | abstract class BaseFragment<T : ViewBinding> : Fragment() { |
使用
1 | class FirstFragment : BaseFragment<FragmentFirstBinding>() { |
其他
Fragment中使用
1 | public class MyFragment extends Fragment { |
Dialog中使用
1 | class MyDialog extends Dialog { |
Adapter 中使用
1 | public class MainAdapter extends RecyclerView.Adapter<MainAdapter.ViewHolder> { |
自定义View中使用
如果我们的自定义View中使用了layout布局,比如layout_my_view.xml,如下
1 |
|
会生成一个名为LayoutMyViewViewBinding.java文件,在自定义View通过如下方式绑定,
1 | public class MyView extends View { |
如果自定义View布局文件中使用merge标签,
1 |
|
此时要写成下面这个样子,
1 | LayoutMyViewViewBinding viewBinding = LayoutMyViewViewBinding.inflate(LayoutInflater.from(context), this); |
include标签的使用
include 标签不带 merge 标签,需要给 include 标签添加 id, 直接使用 id 即可,用法如下所示。
1 | <include |
代码
1 | ActivityMainBinding binding = ActivityMainBinding.inflate(layoutInflater); |
include 标签带 merge 标签,需要通过bind()将merge布局绑定到主布局上,用法如下所示。
1 | <include |
代码
1 | ActivityMainBinding binding = ActivityMainBinding.inflate(layoutInflater); |