初级菜鸟,正在向中级菜鸟努力!
刚刚接触Android开发,有好多东西都不太懂,又喜欢忘东西,干脆写博客记录一下吧。
目录
在activity中使用viewBinding
在Fragment中使用viewBinding
在Adapter中使用ViewBinding
在布局文件中使用viewBinding
include标签的viewBinding使用
merge标签的viewBinding使用
kotlin-android-extensions插件已被废弃,现在推荐使用ViewBinding来进行替代。我的理解是,viewBinding是我们在完成创建一个layout的xml文件时自动生成的一个绑定类,该类以创建的xml文件名+Binding来命名且采用驼峰命名法,如果xml文件名是activity_main.xml,那么绑定类的名称就是ActivityMainBinding,我们可以通过实例化这个绑定类来操纵xml布局文件中的控件属性。以下是viewBinding的简单用法:
在Module级别的build.gradle中写入如下代码:
android {
...
buildFeatures {
viewBinding true
}
}
我们使用MainActivity为例,使用viewBinding来引入activity_main.xml这个布局,实例化这个绑定类为binding,然后就可以使用其中的控件了,这里我们将根布局传入setContentView中代替原来的R.layout.activity_main。我们可以先全局声明一下,在oncreate方法中进行赋值,这样就不用在MainActivity中的其他方法中使用view Binding时重新创建实例了。
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding=ActivityMainBinding.inflate(layoutInflater)
setContentView(R.layout.activity_main)
}
}
假设我们有一个布局文件叫fragment_main.xml,并且想在MainFragment中去显示这个布局。因为kotlin的判空机制,所以代码有些怪怪的。
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
最核心的逻辑仍然是调用FragmentMainBinding的inflate()函数去加载fragment_main.xml布局文件,但由于这是在Fragment当中,所以使用了3个参数的inflate()函数重载,这和我们平时在Fragment中去加载布局文件的方式如出一辙。而在onCreateView()函数中加载的布局,在与其对应的onDestroyView()函数中对binding变量置空,以保证binding变量的有效生命周期是在onCreateView()函数和onDestroyView()函数之间。
这是《第一行代码》中的适配器部分,使用viewBinding改造后的样子。首先改造ViewHolder,让其构造函数接收FruitItemBinding这个参数。但是注意,ViewHolder的父类RecyclerView.ViewHolder它只会接收View类型的参数,因此我们需要调用binding.root获得fruit_item.xml中根元素的实例传给RecyclerView.ViewHolder。
class FruitAdapter(val fruitList: List) : RecyclerView.Adapter() {
inner class ViewHolder(binding: FruitItemBinding) : RecyclerView.ViewHolder(binding.root) {
val fruitImage: ImageView = binding.fruitImage
val fruitName: TextView = binding.fruitName
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = FruitItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val fruit = fruitList[position]
holder.fruitImage.setImageResource(fruit.imageId)
holder.fruitName.text = fruit.name
}
override fun getItemCount() = fruitList.size
主要的改动在ViewHolder和onCreateViewHolder中,其他的 部分并没有改变!
假设我们引入的布局如下:
那么在activity_main.xml布局文件中引入布局可以这么写:
...
一定要记得给include的布局加上id属性,不然到MainActivity中就找不到了!!
最后在MainActivity中通过include布局的id来使用viewBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.titleBar.title.text = "Title"
binding.titleBar.back.setOnClickListener {
}
binding.titleBar.done.setOnClickListener {
}
}
}
使用merge标签时,假设我们引入的布局文件如下:
与include不同的是,在引入时去掉id属性防止崩溃:
然后修改MainActivity中的代码如下:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var titlebarBinding: TitlebarBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
titlebarBinding = TitlebarBinding.bind(binding.root)
setContentView(binding.root)
titlebarBinding.title.text = "Title"
titlebarBinding.back.setOnClickListener {
}
titlebarBinding.done.setOnClickListener {
}
}
}
我们创建了两个viewBinding,一个是activity_main.xml的,另一个是我们引入的merge标签的,然后使用merge标签自动生成的viewBinding的bind方法绑定到activity_main.xml的viewBinding中。
本文参考了郭神的kotlin-android-extensions插件也被废弃了?扶我起来