当前位置:   article > 正文

安卓开发中的ViewBinding使用

viewbinding使用

目录

使用前提

一、在Activity中使用

二、在Fragment中使用

三、在Adapter中使用

四、在引入布局中使用


使用前提

在使用ViewBinding前要在build.gradle工程模块中加入如下配置:

  1. android {
  2. ...
  3. buildFeatures {
  4. viewBinding = true
  5. }
  6. ...
  7. }

在加入上述配置后Android Studio会自动为每一个布局文件都生成一个对应的Binding类。

Binding类的命名规则是将布局文件按驼峰方式重命名后,再加上Binding作为结尾。

例如:

activity_main.xml布局对应的Binding类就是ActivityMainBinding

fragment_main.xml布局对应的Binding类就是FragmentMainBinding

 


一、在Activity中使用

假设在activity_main.xml的布局文件中有一个名为ButtonSubmitButton控件,现在要为这个Button控件设置监听

  1. class MainActivity : AppCompatActivity() {
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. //setContentView(R.layout.activity_main)
  5. //加载布局,并获取布局中的元素引用
  6. //LayoutInflater是一个用于从XML布局文件中实例化布局的类。
  7. //它能够将XML布局文件转换为实际的视图对象
  8. val binding = ActivityMainBinding.inflate(layoutInflater)
  9. //通过 binding.root 获取布局的根视图
  10. setContentView(binding.root)
  11. //binding.ButtonSubmit使用Button控件
  12. binding.ButtonSubmit.setOnClickListener{
  13. //添加点击事件的处理逻辑
  14. }
  15. }
  16. }

如果要在onCreate函数之外使用控件,需要将binding声明成全局变量,如下:

  1. class MainActivity : AppCompatActivity() {
  2. private lateinit var binding: ActivityMainBinding
  3. override fun onCreate(savedInstanceState: Bundle?) {
  4. super.onCreate(savedInstanceState)
  5. setContentView(R.layout.activity_main)
  6. binding = ActivityMainBinding.inflate(layoutInflater)
  7. setContentView(binding.root)
  8. binding.ButtonSubmit.setOnClickListener{
  9. //添加点击事件的处理逻辑
  10. }
  11. }
  12. override fun onDestroy() {
  13. super.onDestroy()
  14. binding.ButtonSubmit.setOnClickListener{
  15. //添加点击事件的处理逻辑
  16. }
  17. }
  18. }


二、在Fragment中使用

方法一:

  1. class MainFragment : Fragment() {
  2. // 使用可空类型定义一个私有的_binding变量,用于存储FragmentMainBinding的实例
  3. private var _binding: FragmentMainBinding? = null
  4. // 定义一个绑定的属性访问器,它返回一个非空的FragmentMainBinding实例。
  5. private val binding get() = _binding!!
  6. // 使用FragmentMainBinding.inflate方法从给定的LayoutInflater和可选的容器中加载布局。
  7. override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
  8. _binding = FragmentMainBinding.inflate(inflater, container, false)
  9. return binding.root
  10. }
  11. override fun onDestroyView() {
  12. // 首先调用super.onDestroyView(),以确保Fragment的基类也执行其销毁逻辑
  13. super.onDestroyView()
  14. // 将_binding设置为null,释放与视图绑定相关的资源
  15. _binding = null
  16. }
  17. }

方法二:

  1. class MainFragment : Fragment(R.layout.fragment_main) {
  2. private lateinit var binding: FragmentMainBinding
  3. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  4. super.onViewCreated(view, savedInstanceState)
  5. // 使用ViewBinding.inflate()方法来加载布局
  6. binding = FragmentMainBinding.inflate(layoutInflater)
  7. // 将binding.root添加到Fragment的视图中
  8. view = binding.root
  9. // 现在可以使用binding对象来访问布局中的元素
  10. binding.exampleTextView.text = "Hello, ViewBinding!"
  11. // 为按钮设置点击事件
  12. binding.exampleButton.setOnClickListener {
  13. // 按钮点击事件的处理逻辑
  14. }
  15. }
  16. }

这两种方法都是使用ViewBinding在Fragment中绑定布局

1、绑定初始化时机:

        第一种方法:在onCreateView中初始化ViewBinding。这是Fragment生命周期中创建视图的阶段,适合在视图创建时立即绑定。
        第二种方法:在onViewCreated中初始化ViewBinding。这是Fragment视图创建后,但尚未设置任何额外的视图设置之前,适合在视图创建之后进行绑定。


2、视图返回方式:

        第一种方法:直接返回binding.root作为onCreateView的结果。这意味着Fragment的根视图是通过ViewBinding生成的。
        第二种方法:在onViewCreated中将binding.root赋值给view参数。这通常发生在Fragment的视图已经通过其他方式(例如,直接使用R.layout.fragment_example)创建之后。


3、视图销毁处理:

        第一种方法:在onDestroyView中将_binding设置为null,以避免内存泄漏。这是因为Fragment可能被重用,所以需要在视图销毁时清理绑定。
        第二种方法:通常不需要在onDestroyView中进行特殊处理,因为lateinit的binding会在onDestroyView之前自动清理。


4、类型安全访问:

        第一种方法:使用_binding!!来强制访问绑定对象,这需要确保_binding在使用前已经被初始化。
        第二种方法:使用lateinit var声明binding,这确保了binding在使用前已经被初始化,并且是不可空的。


三、在Adapter中使用

我们定义fruit_item.xml来作为RecyclerView子项的布局:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"
  4. android:layout_width="match_parent"
  5. android:layout_height="60dp">
  6. <LinearLayout
  7. android:layout_width="match_parent"
  8. android:layout_height="wrap_content"
  9. android:orientation="horizontal">
  10. <ImageView
  11. android:id="@+id/fruitImage"
  12. android:layout_width="40dp"
  13. android:layout_height="40dp"
  14. android:layout_marginLeft="20dp"
  15. android:layout_gravity="center_vertical"
  16. android:layout_marginTop="10dp"/>
  17. <TextView
  18. android:id="@+id/fruitName"
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:layout_gravity="center_vertical"
  22. android:layout_marginTop="10dp"/>
  23. </LinearLayout>
  24. </LinearLayout>

编写不用ViewBindingAdapter来加载和显示这个子项布局:

  1. package com.example.recyclerviewtest
  2. import android.view.LayoutInflater
  3. import android.view.View
  4. import android.view.ViewGroup
  5. import android.widget.ImageView
  6. import android.widget.TextView
  7. import androidx.recyclerview.widget.RecyclerView
  8. import com.example.myapplicationtestexample.R
  9. class FruitAdapter(val fruitList: List<Fruit>) :
  10. RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
  11. inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
  12. val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
  13. val fruitName: TextView = view.findViewById(R.id.fruitName)
  14. }
  15. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
  16. val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_item, parent, false)
  17. return ViewHolder(view)
  18. }
  19. override fun onBindViewHolder(holder: ViewHolder, position: Int) {
  20. val fruit = fruitList[position]
  21. holder.fruitImage.setImageResource(fruit.imageId)
  22. holder.fruitName.text = fruit.name
  23. }
  24. override fun getItemCount() = fruitList.size
  25. }

具体细节实现可移步:

RecyclerView的实现icon-default.png?t=N7T8http://t.csdnimg.cn/5zWcA

编写使用ViewBindingAdapter来加载和显示这个子项布局:

  1. class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
  2. //让ViewHolder的构造函数接收FruitItemBinding这个参数
  3. //ViewHolder的父类RecyclerView.ViewHolder只会接收View类型的参数
  4. //因此需要调用binding.root获得fruit_item.xml中根元素的实例传给RecyclerView.ViewHolder
  5. inner class ViewHolder(binding: FruitItemBinding) : RecyclerView.ViewHolder(binding.root) {
  6. val fruitImage: ImageView = binding.fruitImage
  7. val fruitName: TextView = binding.fruitName
  8. }
  9. //调用FruitItemBinding的inflate()函数去加载fruit_item.xml布局文件
  10. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
  11. val binding = FruitItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
  12. return ViewHolder(binding)
  13. }
  14. override fun onBindViewHolder(holder: ViewHolder, position: Int) {
  15. val fruit = fruitList[position]
  16. holder.fruitImage.setImageResource(fruit.imageId)
  17. holder.fruitName.text = fruit.name
  18. }
  19. override fun getItemCount() = fruitList.size
  20. }

这段代码的核心基本都在onCreateViewHolder()函数ViewHolder函数当中。

这样就不需要再使用findViewById()函数来查找控件实例了,而是调用binding.fruitImagebinding.fruitName就可以直接引用到相应控件的实例。

四、在引入布局中使用

假设我们有如下example.xml布局,是希望作为一个通用布局引入到各布局当中的:

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent" >
  4. <TextView
  5. android:id="@+id/exampleTextView"
  6. android:layout_width="wrap_content"
  7. android:layout_height="wrap_content"
  8. android:layout_centerInParent="true"
  9. android:text="Example"
  10. android:textSize="20sp" />
  11. </RelativeLayout>

假设需要在 activity_main.xml 布局中引入该布局,我们这样引入:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. android:orientation="vertical">
  5. ...
  6. <include
  7. android:id="@+id/example"
  8. layout="@layout/example" />
  9. ...
  10. </LinearLayout>

然后可以直接在MainActivity文件中使用example.xml布局的控件

  1. class MainActivity : AppCompatActivity() {
  2. private lateinit var binding: ActivityMainBinding
  3. override fun onCreate(savedInstanceState: Bundle?) {
  4. super.onCreate(savedInstanceState)
  5. binding = ActivityMainBinding.inflate(layoutInflater)
  6. setContentView(binding.root)
  7. binding.example.exampleTextView.text = "Title"
  8. }
  9. }

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号