作为学习Jetpack的系列文章, 可能会更新得很慢, 本系列文或者应该称之为学习笔记…
观看本文的同学, 应该已经有具备开发简单Android App的能力了, 若是零基础, 那么阅读本文可能有些难懂, 我只能尽量简单解释。
本文所用开发环境以及SDK版本如下,读者应该使用不低于本文所使用的开发环境.
Android Studio 4.0.1
minSdkVersion 21
targetSdkVersion 30
关于 compileSdkVersion
编译版本的说明, 并不是越高越好, 编译版本越高则表示SDK越新, 这种条件下一般会出现许多新问题, 通常是权限问题。所以这里用的是30(Android 10)
。
关于本文中的代码片段, 统一采用伪代码形式。
关于本文使用的编程语言, 统一使用 Kotlin
。
关于 Jectpack
的介绍, 这里就不再赘述了, 百度…
注意:视图绑定在 Android Studio 3.6 Canary 11 及更高版本中可用。
viewBinding
是什么? 直接翻译成中文, 含义就是: 视图绑定
。
首先找到 项目 的 build.gradle
并打开, 举两张图片。
如何开启呢?官方文档中介绍了两种开启方式, 我们分别来看。
方式一:
android {
...
viewBinding {
enabled true
}
...
}
方式二(推荐):
android {
...
buildFeatures {
viewBinding true
}
...
}
这里推荐使用方式二
。
有的还会这么写, 也是可以的。
android {
...
viewBinding {
enabled = true
}
...
}
android {
...
buildFeatures {
viewBinding = true
}
...
}
在 Android 开发中, 传统的寻找控件使用的是 findViewById
, 例如在 res/layout/activity_main.xml
中的界面如下:
...
<TextView
android:id="@+id/myTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
...
对应的TextView的id则是myTextView
, 我们来看在代码中寻找并使用 myTextView
的传统方式。
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//通过Id找到对应的view控件
val myTextView: TextView = findViewById(R.id.myTextView)
//设置新的文本内容
myTextView.text = "你好 世界!"
myTextView.setOnClickListener {
it as TextView
it.text = "你点击了我!"
}
}
...
在使用了viewBinding之后, 则应该是这个样子的。
...
//布局绑定类, 延迟加载
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//binding初始化
binding = ActivityMainBinding.inflate(layoutInflater)
//将根视图作为内容视图
setContentView(binding.root)
//设置新的文本内容
binding.myTextView.text = "你好 世界!"
binding.myTextView.setOnClickListener {
it as TextView
it.text = "你点击了我!"
}
}
...
乍一看, 好像代码量变多了, 而且也没有看到什么优势。
那如果, 是这样呢?
...
lateinit var myTextView: TextView
lateinit var myTextView2: TextView
lateinit var myTextView3: TextView
lateinit var myTextView4: TextView
lateinit var myTextView5: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
myTextView = findViewById(R.id.myTextView)
myTextView2 = findViewById(R.id.myTextView2)
myTextView3 = findViewById(R.id.myTextView3)
myTextView4 = findViewById(R.id.myTextView4)
myTextView5 = findViewById(R.id.myTextView5)
myTextView.text = "你好 世界!"
myTextView2.text = "你好 世界2!"
myTextView3.text = "你好 世界3!"
myTextView4.text = "你好 世界4!"
myTextView5.text = "你好 世界5!"
}
...
使用 viewBinding 之后
...
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.myTextView.text = "你好 世界!"
binding.myTextView2.text = "你好 世界2!"
binding.myTextView3.text = "你好 世界3!"
binding.myTextView4.text = "你好 世界4!"
binding.myTextView5.text = "你好 世界5!"
}
...
值得注意的是, 一旦开启了 viewBinding
那么所有的 xml
布局文件(layout)都将生成一个 Binding
类, 如果需要过滤掉某些 xml
即: 部分xml不生成Binding类
。
那么在xml
的 根节点 中添加 tools:viewBindingIgnore="true"
属性即可。
<LinearLayout
...
tools:viewBindingIgnore="true">
...
LinearLayout>
findViewById
的区别与使用 findViewById 相比,视图绑定具有一些很显著的优点:
这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。
viewBinding
的不足开发过程中, 则需要根据实际情况来决定是否使用 viewBinding
了。