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 + 回车键,如图: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,编译完成后可以发现左边截图的情况,表示我们的 *** 作是成功的。
val binding: ActivityliveDataBinding = DataBindingUtil.setContentVIEw(this,R.layout.activity_live_data)
上面这行代码的几个工具类的说明:
ActivityliveDataBinding:我们上面截图里面生成的类;
DataBindingUtil:一个DataBinding的辅助工具类;
activity_live_data:数据绑定所在的布局文件。
binding.mStudent = Student("陈程", "9年级", "15")
最后是运行效果:
在官方的指南里有这样的写法:
<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所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)