【Android Jetpack】ViewBinding 视图绑定

news/2024/11/29 8:48:30/

文章目录

  • ViewBinding
    • 使用方法
      • 1.build.gradle中开启
      • 2.代码中使用
        • 普通Activity
        • Fragment
        • Adapter
        • include
    • View Binding 的传统使用方式
    • 与findViewById的区别
    • 与DataBinding的对别

ViewBinding

ViewBinding是Google在2019年I/O大会上公布的一款Android视图绑定工具,在Android Studio 3.6中添加的一个新功能,更准确的说,它是DataBinding的一个更轻量变体

使用方法

1.build.gradle中开启

在build.gradle文件中的android节点添加如下代码:

android {...buildFeatures {viewBinding true}
}

重新编译后系统会为每个布局文件生成对应的Binding类,该类中包含对应布局中具有id的所有视图的直接引用。

  • 如果项目中存在多个模块,则需要在每个模块的build.gradle文件中都加上该配置。

  • 假设某个布局文件的名称为result_profile.xml:所生成的绑定类的名称就为ResultProfileBinding

  • 如果布局中的控件没有ID,那么绑定类中不存在对它的引用。

每个绑定类还包含一个 getRoot() 方法,用于为相应布局文件的根视图提供直接引用

如果你希望在生成绑定类时忽略某个布局文件,可以将tools:viewBindingIgnore="true"属性添加到相应布局文件的根视图中:

<LinearLayout...tools:viewBindingIgnore="true" >...
</LinearLayout>

2.代码中使用

普通Activity
class SplashActivity : BaseActivity() {private lateinit var binding: ActivitySplashBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivitySplashBinding.inflate(layoutInflater)setContentView(binding.root)// mtv为xml中定义的idbinding.mtv.text = "fuck the world"}
}
Fragment

在Fragment中,我们需要进行额外的工作来避免内存泄漏,方法是onDestroyView方法中将ViewBinding引用设置为null。 具体如下:

class HomeFragment : Fragment() {private var _binding: HomeFragmentBinding? = null// 只在onCreateView和onDestroyView之间有效private val binding get() = _binding!!override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {_binding = ResultProfileBinding.inflate(inflater, container, false)return binding.root}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)binding.tvHelloWorld.text = "Hello Android!"}override fun onDestroyView() {super.onDestroyView()_binding = null}
}

这里使用了两个不同的变量,并且在onDestroyView()中将_binding变量设置为null。
这是因为碎片的生命周期与活动的生命周期不同,并且碎片有着比它们的视图更长的生命周期,所以如果我们不将其设置为null,可能会发生内存泄漏。
另一个变量用于避免使用!!进行空检查!!通过使一个变量可以为null而另一个变量不为null。

Adapter

还有在Adapter中的使用,因为布局不是只创建一次,而是每个item都会创建,不能像上面那样在Adapter里写一个binding全局变量,不然binding只会得到最后一次创建的视图。所以binding对象应该是给ViewHolder持有。具体如下:

class TextAdapter(private val list: List<String>) : RecyclerView.Adapter<TextAdapter.TextViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TextViewHolder {val binding = ItemTextBinding.inflate(LayoutInflater.from(parent.context), parent, false)//在生成时先给binding赋值,然后传参给ViewHolder的构造器return TextViewHolder(binding)}override fun onBindViewHolder(holder: TextViewHolder, position: Int) {val content = list[position]holder.binding.tvContent.text = content}override fun getItemCount() = list.sizeclass TextViewHolder(val binding : ItemTextBinding) : RecyclerView.ViewHolder(binding.root)
}
include

ViewBinding同样可以被用于include中。
需要对include指定id,通过id来获取,例如:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content"><androidx.appcompat.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="0dp"android:layout_height="?actionBarSize"android:background="?colorPrimary"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><includeandroid:id="@+id/appbar"layout="@layout/app_bar"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val binding: MainLayoutBinding = MainLayoutBinding.inflate(layoutInflater)setContentView(binding.root)setSupportActionBar(binding.appbar.toolbar)//不多说}

View Binding 的传统使用方式

  • 创建和销毁viewBinding的样板代码
  • 如果有很多Fragment,每一个都要拷贝一份相同的代码
  • viewBinding 属性是可空的,并且可变的,这可不太妙

而且使用起来不方便,我们希望用更简单的方式,例如:

class MainActivity : AppCompatActivity() {private val binding by viewBinding(ActivityMainBinding::inflate)
}

怎么办呢?用强大Kotlin委托来重构它。通过属性委托可以自动执行inflate()方法和setContentView()方法。

与findViewById的区别

与使用 findViewById 相比,视图绑定具有一些很显著的优点:

  • Null 安全
    由于视图绑定会创建对视图的直接引用,因此不存在因视图ID无效而引发Null指针异常的风险。此外,如果视图仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用@Nullable标记。
  • 类型安全
    每个绑定类中的字段均具有与它们在XML文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。

这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。

与DataBinding的对别

ViewBinding与DataBinding均会生成可用于直接引用视图的绑定类。但是,ViewBinding旨在处理更简单的用例,与DataBinding相比,具有以下优势:

  • 更快的编译速度
    视图绑定不需要处理注释,因此编译时间更短。
  • 易于使用
    视图绑定不需要特别标记的XML布局文件,因此在应用中采用速度更快。在模块中启用视图绑定后,它会自动应用于该模块的所有布局。

反过来,与数据绑定相比,视图绑定也具有以下限制:

  • 视图绑定不支持布局变量或布局表达式,因此不能用于直接在XML布局文件中声明动态界面内容。
  • 视图绑定不支持双向数据绑定。

考虑到这些因素,在某些情况下,最好在项目中同时使用视图绑定和数据绑定。您可以在需要高级功能的布局中使用数据绑定,而在不需要高级功能的布局中使用视图绑定。


http://www.ppmy.cn/news/1249225.html

相关文章

【LeetCode:1670. 设计前中后队列 | 数据结构设计】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Unity版本使用情况统计(更新至2023年10月)

本期UWA发布的内容是第十三期Unity版本使用统计&#xff0c;统计周期为2023年5月至2023年10月&#xff0c;数据来源于UWA网站&#xff08;www.uwa4d.com&#xff09;性能诊断提测的项目。希望给Unity开发者提供相关的行业趋势&#xff0c;了解近半年来哪些Unity版本的使用概率更…

代码随想录算法训练营第四十三天【动态规划part05】 | 1049. 最后一块石头的重量 II、494. 目标和、474.一和零

1049. 最后一块石头的重量 II 题目链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 求解思路&#xff1a; 等于把石头尽量分成重量相同的两堆 动规五部曲 确定dp数组及其下标含义&#xff1a;容量为j的背包&#xff0c;最多能装…

基于springboot实现班级综合测评管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现班级综合测评管理系统演示 摘要 随着互联网技术的高速发展&#xff0c;人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门就可以通过网络进行系统管理&#xff0c;交易等&#xff0c;而且过程简单、快捷。同样的&#x…

快速操控鼠标行为!Vue鼠标按键修饰符让你事半功倍

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! ⭐ 专栏简介 欢迎来到前端入门之旅&#xff01;这个…

【SparkSQL】基础入门(重点:SparkSQL和Hive的异同、SparkSQL数据抽象)

【大家好&#xff0c;我是爱干饭的猿&#xff0c;本文重点介绍Spark SQL的定义、特点、发展历史、与hive的区别、数据抽象、SparkSession对象。 后续会继续分享其他重要知识点总结&#xff0c;如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下吧】 上一…

GEE 23:基于GEE实现物种分布模型之随机森林法

基于GEE实现物种分布模型之随机森林法 1.物种分布数据2.研究区绘制3.预测因子选择 1.物种分布数据 根据研究目的和需要导入物种数据&#xff1a; // Load presence data var Data ee.FeatureCollection("users/************736/Distribution"); print(Original da…

在虚拟机搭建nignx,和使用本地访问nginx的情况

下载nginx yum install nginx 查看nginx是否安装成功。 nginx -v nginx的配置文件的目录和资源的目录。 先到nginx.conf的目录下&#xff0c;在 /etc/nginx/nginx.conf&#xff0c;编辑它。 vi /etc/nginx/nginx.conf 可以看到默认的html的目录。在 /usr/share/nginx/html 下面…