Android databinding详解(一)--layout解析
来源:互联网 发布:交易猫软件下载 编辑:程序博客网 时间:2024/05/29 18:05
在上一篇文章Android Databinding(初识),介绍了Databinding及代码示例,在这里将从代码的层次上进行Databinding的详细讲解。
本章节主要讲解Data binding的xml文件的代码书写规范。下面直接上硬货。
activity_main文件
<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:fresco="http://schemas.android.com/apk/res-auto"> <data> <import type="wshuttle.com.testmvvm.bean.UserInfo"/> <import type="android.view.View"/> <variable name="imageUrl" type="android.databinding.ObservableInt" /> <variable name="userInfo" type="UserInfo" ></variable> <variable name="show" type="android.databinding.ObservableBoolean" ></variable> <variable name="myEventHandler" type="wshuttle.com.testmvvm.ui.MainActivity.MyEventHandler"></variable> <variable name="orderInfo" type="wshuttle.com.testmvvm.bean.OrderInfo" /> </data> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:fitsSystemWindows="true" android:clipToPadding="false" android:background="@color/bg_color" android:layout_height="match_parent"> <android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:id="@+id/toolbar" android:background="@color/theme_color"> </android.support.v7.widget.Toolbar> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/text_color" android:text="@{String.valueOf(userInfo.id)}" /> <EditText android:cursorVisible="true" android:textCursorDrawable="@drawable/color_cursor" android:layout_width="match_parent" android:textColor="@color/text_color" android:id="@+id/username" android:layout_height="wrap_content" android:text="@={userInfo.name}" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/text_color" android:text="@={userInfo.type}" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/text_color" android:onClick="@{(view) ->myEventHandler.getUser(userInfo)}" android:id="@+id/btnGetName" android:text="获取用户信息" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/text_color" android:onClick="@{myEventHandler::onClick}" android:id="@+id/btnGetType" android:text="获取车主姓名" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/text_color" android:text="@{orderInfo.orderid}" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/text_color" android:text="@{orderInfo.rescueName}" /> <!--<android.support.v7.widget.RecyclerView--> <!--android:layout_width="match_parent"--> <!--android:layout_height="match_parent"--> <!--android:paddingTop="16dp"--> <!--android:id="@+id/recyclerView"--> <!--android:scrollbars = "none"--> <!--/>--> <com.facebook.drawee.view.SimpleDraweeView android:layout_width="50dp" android:layout_height="50dp" android:visibility="@{show.get()?View.VISIBLE:View.GONE}" fresco:image_url="@{imageUrl.get()}" fresco:roundAsCircle="true" /> <ImageView android:layout_width="50dp" android:layout_height="50dp" fresco:image_url="@{imageUrl.get()}" /> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="16dp" android:id="@+id/listView" /> </LinearLayout></layout>
第一眼看去也许跟原先的布局文件与很大变化,但是细看变化之处在于节点的变化,内层的布局与原布局文件是一模一样的。下面针对布局文件中的节点进行解释。
一、layout
在这里,不是以相对布局等布局方式作为根节点,而是以layout作为根节点,它的作用是申明它是一个data binding的布局文件,申明后as会自动编译生成一个ActivityMainBinding(首字母大写,加后缀Binding)的Java类,我们在Activity操作的实际上就是这个Java类。
我们先说一说这个根节点下面引入的命名空间,第一个Android就无需解释了,第二个http://schemas.android.com/apk/res-auto是Data binding进行一些数据属性绑定所需要用到的命名空间,fresco只是一个别名而已无需在意,我的建议是每次如果需要把该布局设置成data binding布局的话,根节点上就添加这样一个命名空间,方便之后的调用。
二、data
此节点是整个布局上最大的变化之处,data节点从字面意思就明白我们数据就在这里了,实际上data节点也就是整个布局文件的数据源,data节点的内容就类似于Java类中引入包以及定义变量的意思。下面说说data下面各个节点的意义。
import:跟Java类一样,就相当于引入Java包,其中有的常用属性有,type:类的路径,需要有包名,alias:为该引入的包去别名(主要为了区分引入两个相同的类名的冲突)。
variable:相当于定义变量,其中常用的属性有,name:变量的名称,type:变量的类型(基本类型,Java类或者Data
bingding类型等)。
下面就本例子下data节点进行解释,本例子下引入了项目的UserInfo,View;定义了imageUrl类型为ObservableInt,userInfo等变量。在这里解释一下ObservableInt是什么类型呢?这个类型是Data binding中定义的类型,如果你布局文件中定义的是此种类型的话,你在Activity中对这个值进行重新赋值的话,界面上会进行刷新,会在改界面上引用改变量地方进行刷新操作(具体如何操作请看),实际上还有另外一种方式可实现单向的刷新操作,imageUrl的类型可以直接为int类型,但是需要Activity调用Binding类的notifyPropertyChanged方法刷新该数据才会刷新界面,代码如下:
ActivityMainBinding bing = DataBindingUtil.setContentView(this, R.layout.activity_main);bing.notifyPropertyChanged(BR.imageUrl);//刷新imageUrl的value
综合来讲,data下面就是定义数据的地方,只不过data binding在进行数据绑定时,实行Activity与layout实现界面更新,需要使用它自己内部定义的方法或者说写上刷新界面的方法。注意在引入类的过程中,要注意xml中有些必须转义的字符,比如说引入Map时,你直接使用Map<Object,String>是会报错的,你必须使用下面的方式
<import type="Map<String,Object>" />
三、数据以及事件绑定
这里是layout文件的重点,data binding是如何实现数据的绑定的呢?我们从上面activity_main.xml文件的源码中进行分析。在这里我们可以看见上面三个文本框的text属性的赋值,看之前我们先看看UsInfo类,这里的UserInfo的属性也使用的是Observable类型的类型,也是为了实现一种单向的绑定。看看我们的EditText的赋值操作, android:text=”@{String.valueOf(userInfo.id)}”这里由于id是int类型,我们使用String.ValueOf进行转化为String,否则会报错,text必须是要为String类型,由于两遍的类型不匹配所以这个字段只能支持一种单向的绑定,也就是Activity刷新layout;android:text=”@={userInfo.name}”就是实现的一种双向的绑定,Activity值改变会刷新数据,EditText输入文本以后会改变Activity对应的实体,如此形成绑定以后则无需再关心layout中的标签了。布局中的id与name的绑定就是数据的单向绑定与双向绑定,@{}为单向的绑定,@={}为双向的绑定。
UserInfo
package wshuttle.com.testmvvm.bean;import android.databinding.ObservableField;import android.databinding.ObservableInt;/** * Observable数据基本类型实现绑定@{}:单向绑定,@={}双向绑定,不是String类型实现双向绑定无法绑定,待解决. * Created by yzy on 2016/9/21. */public class UserInfo{ public ObservableInt id = new ObservableInt(); public ObservableField<String> name = new ObservableField<String>(); public ObservableField<String> type = new ObservableField<String>(); @Override public String toString() { return "UserInfo{" + "id=" + id.toString() + ", name=" + name.toString() + ", type=" + type.toString() + '}'; } public UserInfo(int id, String name, String type) { this.id.set(id); this.name.set(name); this.type.set(type); } public UserInfo() { }}
<EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/text_color" android:text="@{String.valueOf(userInfo.id)}" /> <EditText android:cursorVisible="true" android:textCursorDrawable="@drawable/color_cursor" android:layout_width="match_parent" android:textColor="@color/text_color" android:id="@+id/username" android:layout_height="wrap_content" android:text="@={userInfo.name}" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="@color/text_color" android:text="@={userInfo.type}" />
看完EditText的单向绑定以及双向绑定,我们再来看看其他的绑定吧。下面我们看看Data binding的事件绑定,事件的绑定在这里我是使用自定义的MyEventHandler类来处理这个单击事件(在这里我们可以直接使用onClickListener进行单击事件赋值,在这里为了体现一种data binding的可扩展性我使用的是自定义的事件处理),该类中只有两个方法一个getUser方法,参数有一个UserInfo,一个onClick方法,参数View。我们看布局文件中Button,第一个android:onClick=”@{(view) ->myEventHandler.getUser(userInfo)}”,这里使用的是lambda表达式进行事件的绑定,在这里前面的(view)表示的事件本身,myEventHandler是声明的变量,我们调用myEventHandler.getUserInfo的方法来处理该单击事件,并且将userInfo的参数作为形参;第二个button, android:onClick=”@{myEventHandler::onClick}”直接使用调用的方法,由于它无需传递参数,所以这里就使用::调用方法,调用此方法默认是会把本身的view作为参数传递到方法中。注意:如果没有参数的话,自定义的事件监听的方法也必须要有view作为参数传递进去,否则会报错。
myEventHandler
/** * 自定义事件Handler */ public class MyEventHandler { public void onClick(View view) { switch (view.getId()) { case R.id.btnGetType: { Toast.makeText(MainActivity.this, orderInfo.getRescueName(), Toast.LENGTH_SHORT).show(); break; } } } public void getUser(UserInfo userInfo) { Toast.makeText(MainActivity.this,"id:" + userInfo.id.get() + ",name:" + userInfo.name.get() + ",type:" +userInfo.type.get() ,Toast.LENGTH_SHORT).show(); } }
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/text_color" android:onClick="@{(view) ->myEventHandler.getUser(userInfo)}" android:id="@+id/btnGetName" android:text="获取用户信息" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/text_color" android:onClick="@{myEventHandler::onClick}" android:id="@+id/btnGetType" android:text="获取车主姓名" />
下面我们再看一下,在布局文件中的逻辑判断,这里我们界面上实现的简单的逻辑判断是通过根据show的值显示隐藏图片。 在这里android:visibility=”@{show.get()?View.VISIBLE:View.GONE}”,show是ObservableBoolean类型的,它实际上是一个类,所以通过.get获取它的值,在这里我们可以看见这只是一个简单的?语句操作符,实现了简单的image显示隐藏,实际上可以通过更加复杂的语句进行判断,执行逻辑操作。在这个标签控件下我们还可以看见一个fresco这不是引用的data binding需要的命名空间吗?roundAsCircle是com.facebook.fresco框架(一个比较好的图片框架)自带的属性,但是image_url这明显感觉不像啊,在这里简单说一下,那是我们自己定义的属性,就如同自定义控件的attr一样,自定义属性的方法我们在下一章节进行详细讲解。
<com.facebook.drawee.view.SimpleDraweeView android:layout_width="50dp" android:layout_height="50dp" android:visibility="@{show.get()?View.VISIBLE:View.GONE}" fresco:image_url="@{imageUrl.get()}" fresco:roundAsCircle="true" />
四、注意点
1、在xml中使用的过程中,有些重要的字符是需要转义的,比如>、&等等,需要转义的话可以参考Xml文件必须转义的字符。
2、自定义事件监听时,如果自定义的方法没有参数的话,也需要增加View的形参,否则编译不会通过。
3、在xml中如果需要直接使用字符串的话,需要使用 ` (英文状态下的tab上一个键)。
4、在xml中字符赋值过程中,最好不要直接使用字符进行累加显示比如说android:text=”@{你好啊
+test+哈哈哈
}”,有时会提示utf-8的问题,可能是字符大小超过限制,如果必须要的话最好使用android:text=”@{@string/nihao_string+test+@string/haha_string}”>
五、总结
在本篇文章中主要讲解的data binding在layout的语法以及结构,看完本章后可以继续查看下一章节(Android databinding详解(二)–activity解析),将具体讲解data binding在activity中的具体讲解。
- Android databinding详解(一)--layout解析
- Android databinding详解(二)--activity解析
- Android DataBinding使用详解(一)
- Android DataBinding原理解析
- Android DataBinding完全解析
- Android DataBinding完全解析
- Android DataBinding完全解析
- Android DataBinding原理解析
- android dataBinding详解
- android dataBinding详解
- Android DataBinding 详解
- Android databinding(四)--layout中的特殊使用
- Android DataBinding(数据绑定)详解(一)
- Android DataBinding 基础用法一
- Android DataBinding使用总结(一)
- Android DataBinding (一) 基本用法
- Android开发-数据绑定-DataBinding-AndroidStudio(一)初识DataBinding
- android 解析自定义layout
- Eclipse设置、调优、使用
- Go的50度灰:Golang新开发者要注意的陷阱和常见错误
- mtk hal层smoothzoom(缩放)分析
- tomcat,apache
- Android Glide图片加载框架图片变色变绿解决方法
- Android databinding详解(一)--layout解析
- 图文混排
- select下拉框内容文本过长悬浮显示两种方法
- MySQL 导入数据
- 单例模式
- linux命令随笔(2)
- Python实现KNN算法手写识别数字
- SpringMVC ajax传递json数组到后台报406错误的解决办法
- HDU4738-Caocao's Bridges