Jetpack:DataBinding超详细指南-Kotlin版!,2024年最新android驱动工程师

相关文章:

Jetpack:LifeCycle全面解析(包含检测app启动、进入前台、进入后台例子)。

Jetpack:ViewModel使用指南,实现原理详细解析!

Jetpack:LiveData使用指南,实现原理详细解析!

Jetpack:Room超详细使用踩坑指南!

Jetpack:Room数据库升级详解实战!

文章目录

  • JetPack文章相关目录

  • 简介

  • DataBinding简单使用

  • DataBinding响应事件

  • DataBinding二级页面的绑定

  • BindAdapter简单原理分析

  • 自定义BindAdapter

  • 实现双向绑定

  • 自定义InverseBindingAdapter

  • InverseBindingAdapter简单分析

  • 总结


简介

=====================================================================

DataBinding可以让布局承担部分原本属于页面的工作,可以使得页面与布局文件之间的耦合程度降低。

DataBinding具有以下几点优势:

  1. 部分与UI相关的代码可在布局中完成,代码更简洁,可读。

  2. 不需要使用findViewById()方法。

  3. 布局文件可以包含简单的业务逻辑。

依赖:需要在模块的 build.gradle 文件中将 dataBinding 构建选项设置为 true,如下所示:

android {

buildFeatures {

dataBinding true

}

}

//开启kapt

plugins {

id ‘kotlin-kapt’

}

注意

可以同时使用viewBinding和dataBinding,布局里面使用layout标签,则生成ViewDataBinding类型,否则生成ViewBinding类型的绑定类

DataBinding简单使用

==================================================================================

  • 根据简介的描述在build.gradle开启dataBinding

  • 修改布局文件

在布局文件最外层添加<layout>标签作为根节点。可以手动修改添加<layout>标签;也可以将鼠标移动到原布局跟节点位置,单击浮现的灯泡按钮,然后选择Convert to databinding layout选项,由编译器帮忙进行转化。如下图所示:

在这里插入图片描述

修改完成后的布局如下所示:

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout

android:layout_width=“match_parent”

android:layout_height=“match_parent”>

</androidx.constraintlayout.widget.ConstraintLayout>

  • 实例化布局文件

常规的实例化布局文件方法通过Activity.this.setContentView()方法实例布局文件,然后通过findViewById()方法找到对应的UI控件并使用。使用DataBinding之后可以直接获取对应的Binding类,然后将跟布局设置进布局文件即可;或者使用DataBindingUtil.setContentView()方法直接设置布局文件,且该方法也会返回对应的Binding

举个🌰

private var _binding: ActivityDatabindingBaseBinding? = null

val binding: ActivityDatabindingBaseBinding

get() = _binding!!

//一、直接通过Binding获取Binding类,并且设置布局

private fun initBinding() {

_binding = ActivityDatabindingBaseBinding.inflate(layoutInflater)

setContentView(binding.root)

}

//二、使用DataBindingUtil直接设置布局

private fun initBinding() {

_binding = DataBindingUtil.setContentView(this, R.layout.activity_databinding_base)

}

通过对应的Binding类可以直接方法,布局文件声明的Id类,会将原布局文件声明的id命名,转换为驼峰命名法。

举个🌰

//布局文件的id

<TextView

android:id=“@+id/tv_video_name”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”/>

//使用binding访问

binding.tvVideoName.text = “access ui controls through binding”

  • 将数据传递到布局文件,由布局文件负责进行数据绑定

databinding出现就希望减轻,UI曾对应数据绑定的逻辑,分层更加清晰。所以需要将数据传递到布局文件中,由布局文件负责数据的绑定。

首先声明一个实体类VideoEntity

data class VideoEntity(

val videoName: String? = “迪迦·奥特曼”,

val videoIntroduction: String? = “《迪迦·奥特曼》(ウルトラマンティガ、Ultraman Tiga),是日本圆谷株式会社拍摄的特摄电视剧。是“平成系奥特曼”系列首作,平成三部曲的首作,是奥特曼系列自1980年的 《爱迪·奥特曼》后沉寂数年迎来的重生。于1996年(平成8年)9月7日至1997年(平成9年)8月30日在JNN日本新闻网播放 [1] ,共52话。”,

val videoStarring: String? = “长野博;吉本多香美;高树零;增田由纪夫;影丸茂树;古屋畅一;川地民夫;石桥慧;二又一成”,

val videoImageUrl: String? = “https://img1.baidu.com/it/u=2288494528,306759139&fm=253&fmt=auto&app=120&f=JPEG?w=584&h=378”,

@DrawableRes val localImage: Int = R.drawable.ic_launcher_background

)

将实体类VideoEntity传入到布局文件中,<layout>标签下创建<data>标签(通过编译器直接转换databinding layout 的话,会自动生成<data>标签),<data>标签下创建<variable>标签,指定对象的路径以及对应的名称

  • type实体类的路径

  • name可自定义名称

举个🌰

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”>

<variable

name=“videoEntity”

type=“com.zxf.jetpackrelated.databinding.simpleUse.VideoEntity” />

<androidx.constraintlayout.widget.ConstraintLayout

android:layout_width=“match_parent”

android:layout_height=“match_parent”>

</androidx.constraintlayout.widget.ConstraintLayout>

在activity中,DataBinding直接生成了对应的setter方法。所以可以直接使用setVideoEntity将对象传递给布局类。如下所示:

val videoEntity = VideoEntity()

//绑定实体类

binding.videoEntity = videoEntity

  • 绑定布局变量

将对象传递进去直接,就可以通过@{}直接在布局文件中将对应的变量绑定给控件了

<TextView

android:text=“@{videoEntity.videoName}” />

<TextView

android:text=“@{videoEntity.videoIntroduction}” />

<TextView

android:text=“@{videoEntity.videoStarring}” />

@{}中也可以直接使用静态方法

<TextView

android:text=“@{String.valueOf(1)}” />

DataBinding响应事件

==================================================================================

通过Button控件,演示DataBinding如何响应onClick事件。

  • 创建布局文件转为DataBinding布局
<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”>

<androidx.constraintlayout.widget.ConstraintLayout

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”>

</androidx.constraintlayout.widget.ConstraintLayout>

  • 声明一个EventHandleListener专门处理点击事件

class EventHandleListener(private val videoEntity:VideoEntity) {

fun onButtonClick1(view: View) {

Toast.makeText(context, “click1”, Toast.LENGTH_SHORT).show()

}

fun onButtonClick2(view: View) {

Toast.makeText(context, “click2”, Toast.LENGTH_SHORT).show()

}

}

  • 布局中定义EventHandleListener变量,并将点击事件传递进button。通过双冒号语法::进行调用

<variable

name=“eventHandlerLayout”

type=“com.zxf.jetpackrelated.databinding.simpleUse.SimpleDataBindingActivity.EventHandleListener”/>

<Button

android:onClick=“@{eventHandlerLayout::onButtonClick1}”

/>

<Button

android:onClick=“@{eventHandlerLayout::onButtonClick2}”

/>

  • activity中将EventHandleListener传递给布局文件

binding.eventHandler = EventHandleListener(videoEntity)

DataBinding二级页面的绑定

=====================================================================================

简单来说就是怎么将,数据传递到通过<include>标签包裹的二级页面呢?

下面就将上面的按钮响应事件通过<include>包裹一下,将EventHandleListener进行一个二级传递。

  • 在一级页面定义<include>,将上面的按钮布局包裹进来

<include

android:id=“@+id/in_bt”

layout=“@layout/layout_databinding_base” />

  • 在一级页面同样声明一下EventHandleListener变量,可以通过二级页面声明的EventHandleListener的name,将对象直接传递给二级页面

<variable

name=“eventHandler”

type=“com.zxf.jetpackrelated.databinding.simpleUse.SimpleDataBindingActivity.EventHandleListener” />

<include

android:id=“@+id/in_bt”

layout=“@layout/layout_databinding_base”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

app:eventHandlerLayout=“@{eventHandler}”/>

BindAdapter简单原理分析

====================================================================================

当启用databinding之后,会生成大量的类,其中包括针对UI的各种命名为XXXBindAdapter的类。

截取一下TextViewBindingAdapter类的部分源码。源码展示了DataBinding库针对android:text属性所编写的代码

@BindingAdapter(“android:text”)

public static void setText(TextView view, CharSequence text) {

final CharSequence oldText = view.getText();

if (text == oldText || (text == null && oldText.length() == 0)) {

return;

}

if (text instanceof Spanned) {

if (text.equals(oldText)) {

return; // No change in the spans, so don’t set anything.

}

} else if (!haveContentsChanged(text, oldText)) {

return; // No content changes, so don’t set anything.

}

view.setText(text);

}

在布局文件中通过@{}绑定的text,最终通过生成的BindingImpl类,调用了对应的setText静态方法。

所以总的来说,在布局文件里面绑定的数据,可以调用到BindingAdapter修饰的静态方法

自定义BindAdapter

=================================================================================

仅官方提供的BindAdapter肯定是不够的,所以需要自定义BindAdapter,实现更多的更复杂的业务关系。

下面展示使用ImageView自定义BindAdapter。

  • BindAdapter注解介绍

@Target(ElementType.METHOD)

public @interface BindingAdapter {

String[] value();

boolean requireAll() default true;

}

  • value 即分配给布局文件中使用的名字

  • requireAll 如果需要一下子定义多个value,用于区别是否所有的都需要,默认为true,如果为true,则布局文件中,一旦使用了其中一个其他的也必须要声明,不然编译不通过。

  • 使用glide进行图片加载

添加依赖和网络访问权限

implementation ‘com.github.bumptech.glide:glide:4.12.0’

annotationProcessor ‘com.github.bumptech.glide:compiler:4.12.0’

  • 定义ImageView的BindAdapter类

需要注意的是,BindingAdapter中的方法均为静态方法。第1个参数为调用者本身,即ImageView;第2个参数是布局文件在调用该方法时传递过来的参数

对于Kotlin来说,只需要将函数声明为顶级函数,就对应java的静态方法了。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
img

学习交流

群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img
//img-blog.csdnimg.cn/13f2cb2e05a14868a3f0fd6ac81d625c.png)

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-YXBnFg0d-1712738793398)]

学习交流

[外链图片转存中…(img-aA55aZmR-1712738793399)]

[外链图片转存中…(img-7bWNqWJv-1712738793399)]

群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。

35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-he1tUYWN-1712738793399)]

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值