【Android Jetpack】ViewBinding 视图绑定

文章目录

  • 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.mzph.cn/news/183182.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣 --- 三数之和

目录 题目描述&#xff1a; 思路描述&#xff1a; 代码&#xff1a; 提交结果&#xff1a; 官方代码&#xff1a; 官方提交结果&#xff1a; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k…

使用STM32 HAL库驱动烟雾传感器的设计和优化

STM32 HAL库是STMicroelectronics提供的针对STM32系列微控制器的一套硬件抽象层库&#xff0c;可以简化开发过程并提供对各种外设的支持。本文将介绍如何使用STM32 HAL库来驱动烟雾传感器&#xff0c;并对传感器数据采集和处理进行优化。将包括HAL库的初始化、模拟信号采集、数…

大数据项目前三层--学习笔记

ODS层搭建 原始数据层&#xff0c;ODS层是原始数据的完整备份&#xff0c;不做任何修改。为了方便DWD层使用&#xff0c;一般会在ODS层增加抽取数据的日期字段。 1,列式存储和行式存储 行存储的特点&#xff1a; 查询满足条件的一整行&#xff08;所有列&#xff09;数据的时…

UE5、CesiumForUnreal实现加载GeoJson绘制多面(MultiPolygon)功能(支持点选高亮)

文章目录 1.实现目标2.实现过程2.1 数据与预处理2.2 GeoJson解析2.3 Mesh构建与属性存储2.4 核心代码2.5 材质2.6 蓝图应用测试3.参考资料1.实现目标 在之前的文章中,基于GeoJson数据加载,实现了绘制单面功能,但只支持单个要素Feature。本文这里实现对Geojson内所有面要素的…

Abaqus飞机起落架扭力臂拓扑优化

Abaqus飞机起落架扭力臂拓扑优化 Abaqus除了可以对结构进行强度分析&#xff0c;同样也自带强大的优化功能&#xff0c;下面通过一个简 单的实例演示在Abaqus中进行拓扑优化&#xff0c;另外&#xff0c;如果需要更加强大的拓扑优化仿真&#xff0c;可以 在TOSCA中进行。 定义接…

一个完整的cuda动态链接库工程

0. 思路 为了能把理念说通&#xff0c;使用了 step by step 的方式&#xff0c;一步步迭代会觉得比较合理。源代码从nv官方vectorAdd改过来的。 step 1&#xff0c; 单 cu 文件的可执行文件版本 源代码 main_app.cu #include <stdio.h> #include <cuda_runtime.h&g…

redis-基础

数据类型 1.1 字符串 String是最常用的数据格式&#xff0c;普通的kay-value都归结为此类&#xff0c; value值不仅可以是string&#xff0c;可以是数字。 使用场景&#xff1a;通过用户的访问次数为依据封锁ip&#xff0c;可以将用户的访问次数已string类型记录在redis中&am…

软件工程(九)

软件过程 定义 是软件生存周期中的一系列相关软件工程活动的集合&#xff0c;活动是任务的集合。 任务是将输入变换为输出的操作。 活动的执行可以是顺序的&#xff0c;重复的&#xff0c;并行的、嵌套的。 每一个软件过程由一组工作任务、项目里程碑、软件工程产品和交付…

最稳定的app分发平台怎么签到领取点数

第一步 登点击录《咕噜分发平台官网》 ●首页点击绿色箭头所指向的转盘 ●点击天数然后点击今日签到 ● 图下是我们的签到应该获得的点数 ● 图下是我们的签到累积获得的点数&#xff0c;以及连续签到的次数 控制台查看 查看签到获得点数通知 ●查看签到结果以及累积签到点数…

使用影刀指令+python实现简单的长文本乱序加密

本文意在利用影刀指令python代码&#xff0c;实现一种较为简单的长文本加密和解密&#xff0c;流程结构分为两步&#xff1a; 加密原理–是把字符转为列表&#xff0c;利用列表random模块中的shuffle函数做随机乱序。解密原理–是利用了列表的索引追踪&#xff0c;先前创建字典…

原神:夏洛蒂是否值得培养?全队瞬抬治疗量不输五星,但缺点也很明显

作为四星冰系治疗角色&#xff0c;夏洛蒂的实战表现可以说相当让人惊喜。不仅有相当有意思的普攻动作以及技能特效&#xff0c;而且她还有治疗和挂冰等功能性。下面就来详细聊聊夏洛蒂是否值得培养。 【治疗量让人惊喜&#xff0c;但也有缺点】 说实话&#xff0c;在使用夏洛蒂…

AcWing 3555:二叉树(北京大学考研机试题)→公共父结点

【题目来源】https://www.acwing.com/problem/content/description/3435/【题目描述】 如下图所示&#xff0c;由正整数 1, 2, 3, … 组成了一棵无限大的&#xff08;满&#xff09;二叉树。 1/ \2 3/ \ / \4 5 6 7 /\ /\ /\ /\ ... ... 从任意一个结点到根结点&…

【Web】NewStarCTF Week3 个人复现

①Include &#x1f350; ?filephpinfo 提示查下register_argc_argv 发现为on LFI包含 pearcmd命令执行学习 pearcmd.php文件包含妙用 ?file/usr/local/lib/php/pearcmd&config-create/<?eval($_POST[a])?>./ha.php ?file./ha post传&#xff1a; asystem…

C++ 通过CryptoPP计算Hash值

Crypto (CryptoPP) 是一个用于密码学和加密的 C 库。它是一个开源项目&#xff0c;提供了大量的密码学算法和功能&#xff0c;包括对称加密、非对称加密、哈希函数、消息认证码 (MAC)、数字签名等。Crypto 的目标是提供高性能和可靠的密码学工具&#xff0c;以满足软件开发中对…

3 测试驱动的Spring Boot应用程序开发数据层示例

文章目录 用户故事数据模型选择数据库SQL与NoSQLH2、Hibernate和JPA Spring Boot Data JPA依赖关系和自动配置Spring Data JPA技术栈数据源&#xff08;自动&#xff09;配置 实体存储库存储User和ChallengeAttempt显示最近的ChallengeAttempt服务层控制器层用户界面 小结 文章…

go学习之文件操作与命令行参数

文章目录 一、文件操作1.基本介绍2.常用文件操作函数和方法3.关于文件操作应用实例4.写文件操作应用实例&#xff08;创建文件并写入文件&#xff09;1&#xff09;基本介绍2&#xff09;基本应用实例-方式一 5.判断文件是否存在6.统计英文、数字、空格和其他字符数量 二、命令…

微信开发者工具导入uniapp项目

引言 作为一名经验丰富的开发者,我将教会你如何在微信开发者工具中导入uniapp项目。在本文中,我将详细介绍整个导入流程,并提供每一步所需的代码和注释。 导入流程概览 下表展示了导入uniapp项目到微信开发者工具的步骤: 步骤描述1在微信开发者工具中新建项目2设置项目信…

武汉凯迪正大KDZD5289硫化曲线测试仪(电脑无转子硫化仪)

电脑无转子硫化仪 硫化时间测试仪 硫化曲线仪 硫化曲线测试仪 武汉凯迪正大KDZD5289产品概述 KDZD5289硫化曲线测试仪&#xff08;电脑无转子硫化仪&#xff09;采用电脑控制进口温控仪进行准确控温&#xff0c;计算机适时进行数据处理并可进行统计、分析、存储对比等&#xff…

报错解决:You may need an additional loader to handle the result of these loaders.

报错信息如下 vue 项目 Module parse failed: Unexpected token (1:9) File was processed with these loaders:* ./node_modules/vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js* ./node_modules/babel-loader/lib/index.js* ./node_modules/eslint-loader/in…

golang channel执行原理与代码分析

使用的go版本为 go1.21.2 首先我们写一个简单的chan调度代码 package mainimport "fmt"func main() {ch : make(chan struct{})go func() {ch <- struct{}{}ch <- struct{}{}}()fmt.Println("xiaochuan", <-ch)data, ok : <-chfmt.Println(&…