Android Jetpack 架构组件之 DataBinding

Android Jetpack 架构组件之 DataBinding,第1张

概述一、DataBinding简介:DataBinding,顾名思义即为数据绑定,其推出目的就是为了减少繁琐的代码,使代码更加的简洁、可读性更强。使用DataBinding会让我们的布局文件不简简单单的只有一个布局文件的作用,还包含和很多的逻辑。可以大量减少Java代码。同时DataBinding还会让我们 一、DataBinding 简介:

DataBinding ,顾名思义即为数据绑定,其推出目的就是为了减少繁琐的代码,使代码更加的简洁、可读性更强。使用 DataBinding 会让我们的布局文件不简简单单的只有一个布局文件的作用,还包含和很多的逻辑。可以大量减少 Java代码。

同时DataBinding还会让我们的代码更有层级,结构更加的清晰完善,数据能够单向或者双向绑定到布局文件当中。这样有助于防止内存泄露,而且能够自动进行空检测以避免空指针异常。

二、 DataBinding 的集成

**DataBinding只能运行在AndroID 4.0(API>14)或更高版本的设备上。**使用DataBinding之前我们需要完成基本配置:

1、在 App的build.gradle 里面引入对DataBinding的支持:
//引入对 DataBinding 的支持androID {    buildFeatures {        dataBinding = true        vIEwBinding = true// for vIEw binding    }}
2、在 gradle.propertIEs 文件当中添加数据绑定的编译器:
androID.databinding.enableV2=true
3、在布局文件当中,选中根布局的VIEwGroup,然后按住Alt + 回车键,如图:


对比我们Alt + 回车键 *** 作之前能够发现,xml布局文件里面新增了标签。具体情况我们稍后细说。到这里,DataBinding的继承配置工作就完成了。接下来就是主菜:DataBinding的应用。

三、DataBinding 的简单使用

DataBinding有很多应用场景和方法,下面我们只介绍一下 DataBinding 的简单的使用,其他的在另外一部分里面介绍。

data标签构建了VIEw和Model之间的连接通道。通过data标签就可以把Model层与 VIEw层绑定在一起。具体使用如下:

1、我们首先创建一个数据类型:
data class Student(var name:String, var grade:String, var age:String) {   ...... }
2、接下来的 *** 作基本上都是在xml布局文件里面:

首先,在xml的data标签当中声明要使用到的变量、类的全路径;
然后,引用数据类型;
最后,在需要的地方给属性赋予默认值。关于xml里面的 *** 作情况见下面的代码以及关键信息和字段的说明:

name:为方便我们使用,给数据类起的别名,比如我们的数据类型是Student,下面方式一和方式二里面的name都是我们给Student起的别名,我们总不至于直接使用Student,这样跟Student.kt重合不容易区分开,容易出问题。

type:指定我们要引用的数据类的完整路径名,比如“com.androIDjetpack.livedata.Student”是Student的完整路径。

import:如果我们使用的Student类型会在很多地方用到,我们也可以采用 import 的方式引进来,这样我们就不用每次都指明整个包名的路径了。

<data>    <!--方式一-->    <variable        name="sudentInfo"        type="com.androIDjetpack.databinding.Student" />    <!--方式二-->    <import type="com.androIDjetpack.databinding.Student"/>    <variable        name="mStudent"        type="Student" /></data>

实际使用中数据的引用方式:

@{***.***}

另外,在初始状态下Student的所有成员属性都是没有值的,不方便我们在不居中观察状态.
因此我们有两个方案来解决:
一是:

tools:text="***"

tools开头的属性在布局的时候会显示出来,但在正式运行的时候不会。

二是:

androID:text="@{***.***, default = vaue}"

方案二有个缺陷:value值里面不能包含标点符号,无论中英文标点符号,只能包含少量的特殊字符,比如“$”、“_”等等。而方案一则灵活不受限制。

<layout xmlns:androID=http://schemas.androID.com/apk/res/androID    xmlns:tools=http://schemas.androID.com/tools    xmlns:app="http://schemas.androID.com/apk/res-auto">    <data>        <!--方式一-->        <variable            	        name="sudentInfo"      	        type="com.androIDjetpack.livedata.Student" />        <!--方式二-->        <import type="com.androIDjetpack.livedata.Student"/>        <variable            	        name="mStudent"      	        type="Student" />    </data>    <androIDx.constraintlayout.Widget.ConstraintLayout        androID:layout_wIDth="match_parent"                androID:layout_height="match_parent"        tools:context=".livedata.liveDataActivity"             androID:background="@mipmap/fire">                <TextVIEw            androID:ID="@+ID/tvname"	            androID:layout_wIDth="wrap_content"	            androID:layout_height="wrap_content"            androID:layout_marginStart="10dp"              androID:layout_margintop="10dp"              androID:text="@{mStudent.name}"                 tools:text="名字"                app:layout_constraintleft_toleftOf="parent"            app:layout_constrainttop_totopOf="parent"/>                    <TextVIEw            androID:ID="@+ID/tvGrade"                androID:layout_wIDth="wrap_content"                 androID:layout_height="wrap_content"            androID:layout_marginStart="10dp"               androID:layout_margintop="10dp"                androID:text="@{mStudent.grade}"             	tools:text="年级"         	app:layout_constraintleft_toRightOf="@+ID/tvname"         	app:layout_constrainttop_totopOf="parent"/>        	        <TextVIEw            androID:ID="@+ID/tvAge"               androID:layout_wIDth="wrap_content"		            androID:layout_height="wrap_content"            androID:layout_marginStart="10dp"   	            androID:layout_margintop="10dp"            androID:text="@{mStudent.age, default=年龄18}"            app:layout_constraintleft_toRightOf="@+ID/tvGrade"            app:layout_constrainttop_totopOf="parent"/>    </androIDx.constraintlayout.Widget.ConstraintLayout>

layout布局文件写好之后,再Build→→Rebuild Project,编译完成后可以发现左边截图的情况,表示我们的 *** 作是成功的。


默认情况下,这个类名是基于布局文件的名称创建的,将其转换为Pascal大小写并向其添加Binding后缀。上面的布局文件名是activity_live_data.xml,因此相应的生成类是 ActivityliveDataBinding

3、接下来我们就需要在Activity当中为「userInfo」赋值:
val binding: ActivityliveDataBinding = DataBindingUtil.setContentVIEw(this,R.layout.activity_live_data)

上面这行代码的几个工具类的说明:

ActivityliveDataBinding:我们上面截图里面生成的类;
DataBindingUtil:一个DataBinding的辅助工具类;
activity_live_data:数据绑定所在的布局文件。

binding.mStudent = Student("陈程", "9年级", "15")

最后是运行效果:

四、DataBinding进阶1、避免使用复杂的表达式

在官方的指南里有这样的写法:

<data>    <import type="com.example.MyStringUtils"/>        <variable name="user"     	type="com.example.User"/></data><TextVIEw    androID:text="@{MyStringUtils.cAPItalize(user.lastname)}"    androID:layout_wIDth="wrap_content"    	    androID:layout_height="wrap_content"/>

或者这样的

<TextVIEw    androID:layout_wIDth="wrap_content"    	    androID:layout_height="wrap_content"    androID:text="@{String.valueOf(index + 1)}"		androID:visibility="@{age < 13 ? VIEw.GONE : VIEw.VISIBLE}"	androID:Transitionname='@{"image_" + ID}'		androID:text="@{@string/nameFormat(firstname, lastname)}"	androID:padding="@{large? @dimen/largepadding : @dimen/smallpadding}"	androID:text="@{map[`firstname`]}"/>

需要注意:

这些都不代表最佳实践,只能说支持这样的写法、用法。上面的写法、用法它有一个很大的弊端,相信很多刚入门DataBinding的人都遇到过找不到binding文件的错,然后被劝退,原因无外乎就是表达式写错、variable的类路径不对或者没import相应的类(比如VIEw)等等,都与复杂的表达式有关系,而DataBinding报错也不太智能,有时不能准确定位。

所以建议不要在xml里进行复杂的数据绑定,复杂的逻辑处理尽量放到viewmodel里,xml只绑定简单的基础数据类型。比如下面的 *** 作:

<data>    		<variable name="vm" 		type="com.example.Userviewmodel"/>		</data><TextVIEw    androID:text="@{ vm.cAPItalizeLastname}"      androID:layout_wIDth="wrap_content"      androID:layout_height="wrap_content"    androID:hint="@{ vm.index}"       androID:visibility="@{vm.showname}"  	    androID:Transitionname='@{ vm.traname}'/>
2、点击事件的命名和处理

DataBinding支持的写法有以下几种:

androID:onClick="@{presenter.onClick()}" //1.方法引用androID:onClick="@{()->presenter.onClick()}" //2.lamda表达式androID:onClick="@{(vIEw)->presenter.onClick(vIEw)}" //3.lamda表达式androID:onClick="@{()->presenter.onClick(item)}"//4.带参数lamda表达式androID:onClick="@{(vIEw)->presenter.onClick(vIEw, item)}"//5.带参数lamda表达式

选择很多,而且五花八门,有的喜欢直接使用viewmodel里的方法,有的直接将Activity或者fragment作为handler,还有的可能会在activity/fragment里写一个内部类作为presenter,然后由于方法名也可以自定义,所以很可能出现你叫presenter.save(),另一个叫**(v)->handler.onSave(v)**的情况。
比较糟糕的写法:

<layout>    <data>        <variable        	        name="vm"        	        type="io.ditclear.app.viewmodel.Animalviewmodel"/>        <variable        	        name="handler"        	        type="io.ditclear.app.vIEw.AnimalActivity"/>        <variable        	        name="presenter"        	        type="io.ditclear.app.vIEw.AnimalActivity.Presenter"    </data>    <linearLayout        tools:context="io.ditclear.app.vIEw.AnimalActivity">                <button                    androID:onClick="@{vm.shoutWhat()}"/>        <button                    androID:onClick="@{(v)->handler.shout(v)}"/>        <button                    androID:onClick="@{()->presenter.onShout()}"/>    </linearLayout></layout>

比较好的写法有两种:

一是不依赖于dataBinding,但是也不用传统通过OnClickListener接口实现。

Xml里面实现如下:

<TextVIEw    androID:ID="@+ID/tvAge"          androID:layout_wIDth="wrap_content"        androID:layout_height="wrap_content"    androID:onClick="ageClick"         androID:text="@{mStudent.age, default=年龄18}"    app:layout_constraintleft_toRightOf="@+ID/tvGrade"    app:layout_constrainttop_totopOf="parent"/>

对应的kotlin代码里面:

fun ageClick(mVIEw:VIEw){    	println("试试这样的写法????????????????????")	}

第二就是,通过dataBinding实现:

<layout>    <data>        <variable            	        name="vm"            	        type="io.ditclear.app.viewmodel.Animalviewmodel"/>	                <variable            	        name="presenter"      	        type="io.ditclear.app.helper.Presenter"    </data>    <linearLayout               	tools:context="io.ditclear.app.vIEw.AnimalActivity">    	        <button            	        androID:ID="@+ID/save_btn"       	        androID:onClick="@{(v)->presenter.onClick(v)}"/>	                <button    			        androID:ID="@+ID/submit_btn"    	        androID:onClick="@{(v)->presenter.onClick(v)}"/>    </linearLayout></layout>

然后kotlin代码里这样的接口:

interface Presenter : VIEw.OnClickListener {    	overrIDe fun onClick(v: VIEw)	}

这里推荐使用(v)->presenter.onClick(v)的写法,原因之一是比较直观一点,其二是需要参数vIEw。

接着在activity/fragment中来实现Presenter接口,处理点击事件:

class AnimalActivity : AppCompatActivity(), Presenter {    private var mBinding: AnimalActivityBinding? = null    private var mviewmodel: Animalviewmodel? = null        overrIDe fun onCreate(@Nullable savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)                mBinding = DataBindingUtil.setContentVIEw(this, R.layout.animal_activity)        val animal = Animal("dog", 1)        mviewmodel = Animalviewmodel(animal)        mBinding.setVm(viewmodel)        mBinding.setPresenter(this)    }    @SingleClick    fun onClick(v: VIEw) {        //根据ID进行区分        when (v.ID) {            R.ID.save_btn -> save()            R.ID.delete_btn -> delete()            R.ID.submit_btn -> submit()        }}    private fun save() {//调用viewmodel的方法        mviewmodel.save()    }		private fun delete() {//调用viewmodel的方法        mviewmodel.delete()    }		private fun submit() {//调用viewmodel的方法        mviewmodel.submit()    }}

其实仔细观察发现:上面的第二种方法跟传统的方式一样,没什么本质区别。

总结

以上是内存溢出为你收集整理的Android Jetpack 架构组件之 DataBinding全部内容,希望文章能够帮你解决Android Jetpack 架构组件之 DataBinding所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1054048.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存