您的位置:首页 > 其它

Data Binding

2016-06-01 16:49 357 查看
第一步 配置
在build.gradle文件

android {
    ....
    dataBinding {
        enabled =true
    }
}


第二步 编写Data Binding布局文件

<?xml version="1.0" encoding="utf-8"?>
<layoutxmlns:android="http://schemas.android.com/apk/res/android">
   <data>
       <variablename="user"type="com.example.User"/>
   </data>
   <LinearLayout
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
   </LinearLayout>
</layout>

<variable/> 用来声明变量,name变量名字,type类型包名+类名
使用:@{user.username},会调用user.getUsername方法或username()方法

<TextViewandroid:text="@{user.username}"


第三步  Binding Data
     Data Binding布局文件,会生成布局文件名对应的类,例如:main_activity.xml,生成MainActivityBinding类,如果<data/>没有子标签,不会生成
   
   在onCreate方法中,不要调用setContentView,用下面代码替代

MainActivityBinding binding =DataBindingUtil.setContentView(this, R.layout.main_activity);
    User user =newUser("Test","User");
    binding.setUser(user);

   可以这样

MainActivityBinding binding =MainActivityBinding.inflate(getLayoutInflater());

如果布局文件,包括ListView,RecyclerView

ListItemBinding binding =ListItemBinding.inflate(layoutInflater, viewGroup,false);
//or
ListItemBinding binding =DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup,false);


Binding Events
    和绑定数据差不多

publicclass ButtonHandler{
    publicvoid click(View view){...}
}


<variablename="handler"type="com.example.Handler"/>

<Button android:onClick="@{handlers.click}"/>


特殊点击事件

ClassListener SetterAttribute
SearchView
setOnSearchClickListener(View.OnClickListener)
android:onSearchClick
ZoomControls
setOnZoomInClickListener(View.OnClickListener)
android:onZoomIn
ZoomControls
setOnZoomOutClickListener(View.OnClickListener)
android:onZoomOut
Data Binding 布局详解
    Imports:引入类,像Java一样引入类。

<data>
    <importtype="android.view.View"/>
</data>

<TextViewandroid:visibility="@{user.isAdult ? View.VISIBLE : View.GONE}"/>

    如果引入多个相同类名,可以使用alias指定别名

<importtype="com.example.real.estate.View"alias="Vista"/>

    集合,后面User表示泛型

<variablename="userList"type="List<User>"/>


    引入静态field或方法

 
  java.lang.*
 里的类自动引入

Variables
    有个默认的context变量,被binding表达式使用。root View的getContext()。如果声明了context变量,覆盖功能就不起作用。

自定义生成Binding Class名字
    <dataclass="ContactItem"> </data>
    <data class=".ContactItem"> </data>

    <data class="com.demo.ContactItem"> </data>

Includes
    指定命名空间 xmlns:bind="http://schemas.android.com/apk/res-auto" ,name.xml必须有个
user
变量


<LinearLayout>
       <includelayout="@layout/name"bind:user="@{user}"/>
   </LinearLayout>


   不支持

<merge>
       <includelayout="@layout/name"
           bind:user="@{user}"/>
       <includelayout="@layout/contact"
           bind:user="@{user}"/>
   </merge>


Expression Language
    有很多像Java expression

Mathematical 
+
- / * %

String concatenation 
+

Logical 
&&
||

Binary 
&
| ^

Unary 
+
- ! ~

Shift 
>>
>>> <<

Comparison 
==
> < >= <=

instanceof

Grouping 
()

Literals - character, String, numeric, 
null

Cast
Method calls
Field access
Array access 
[]

Ternary operator 
?:


    没有的操作

this

super

new

Explicit generic invocation

  Null Coalescing Operator (??)
    空操作,左边表达式不空时,使用左边表达式值,否则使用右边表达式值
    android:text="@{user.displayName
?? user.lastName}"

避免空指针错误
    @{user.name} 如果user为空,那么user.name为null,基本类型是默认值

集合,array,list,map可以使用
[]
 操作符访问

android:text="@{list[index]}"
android:text="@{map[key]}"


字符串,可以使用单双引号交替,就像前端那种写法

android:text='@{map["firstName"]}'

Resources

android:text="@{@string/nameFormat(firstName, lastName)}"

后面firstName,lastName是参数,等于调用getResources.getString(R.string.nameFormat, firstName, lastName);

TypeNormal ReferenceExpression Reference
String[]@array@stringArray
int[]@array@intArray
TypedArray@array@typedArray
Animator@animator@animator
StateListAnimator@animator@stateListAnimator
color 
int
@color@color
ColorStateList@color@colorStateList
Data Objects
    Data Binding 使用的POJO对象,POJO对象改变,不会通知UI更新的。Data Binding提供三种数据改变通知机制:
        Observable
objects, observable
fields, and observable
collection

Observalbe Objects
    Observable 接口有增加和移除listener方法,通过变换由开发者调用,可以继承它的子类BaseObservable.
    在getter方法上添加@Bindable注解,该注解在编译时生成BR类,在module
package默认根包下
    在setter通知数据变化notifyPropertyChanged(BR.firstName);
ObservableFields
    还有
ObservableBoolean
ObservableByte
ObservableChar
ObservableShort
ObservableInt
ObservableLong
ObservableFloat
,
ObservableDouble
,
and 
ObservableParcelable


publicfinalObservableField<String> sex =newObservableField<>();

使用:

<TextView android:text="@{user.sex}"/>

user.sex.set("男");
int age = user.age.get();

Observable Collections
    把原来使用的集合类,换成下面这种

ObservableArrayMap<String,Object> user =newObservableArrayMap<>();

ObservableArrayList<String> lists = new ObservableArrayList<>();


生成 Binding

创建

MyLayoutBinding binding =MyLayoutBinding.inflate(layoutInflater);
MyLayoutBinding binding =MyLayoutBinding.inflate(layoutInflater, viewGroup,false);

MyLayoutBinding binding =MyLayoutBinding.bind(viewRoot);

ViewDataBinding binding =DataBindingUtil.inflate(LayoutInflater, layoutId,
    parent, attachToParent);
ViewDataBinding binding =DataBindingUtil.bindTo(viewRoot, layoutId);

根据Id生成View对象
    这机制比findViewById更快

<TextView
android:id="@+id/username"/>

<TextView
android:id="@+id/userAge"/>




变量
    每个变量都提供访问方法
ViewStubs
    viewStub介绍http://blog.csdn.net/hitlion2008/article/details/6737537/
        当viewstub inflate布局时,binding需要为新的布局重新创建,ViewStubProxy监听
ViewStub
's
ViewStub.OnInflateListener并及时创建binding,ViewStubProxy允许开发者设置OnInflateListener
,并创建binding


Advanced Binding
    binding class需要动态生成,例如RecyclerView.Adapter,在Holder提供getBinding方法返回Binding对象

publicvoid onBindViewHolder(BindingHolder holder,int position){
   final T item = mItems.get(position);
   holder.getBinding().setVariable(BR.item, item);
   holder.getBinding().executePendingBindings();
}


   变量数据变化时,binding将会下一帧改变,如果需要立即执行,调用 executePendingBindings()方法
 
 只要不是集合变量数据,可以后台线程进行修改数据值,不用担心同步问题。Data binding will localize each variable / field
Attribute Setters
    对于一个属性,data binding尽量找setAttribute方法,命名空间不重要,主要是属性名字
    例如:DrawerLayout 没有任何属性,但提供大量的setter方法,所有能这样使用。


<android.support.v4.widget.DrawerLayout    app:scrimColor="@{@color/scrim}"
    app:drawerListener="@{fragment.drawerListener}"/>
Renamed Setters
    更改属性关联的setter方法,替换原来的setter方法,通过BindingMethods注解关联一个setter方法,

@BindingMethods({
       @BindingMethod(type ="android.widget.ImageView",
                      attribute ="android:tint",
                      method ="setImageTintList"),
})

Custom Setters
    有的属性需要自定义binding逻辑,例如:
android:paddingLeft没有对应的setter方法,只存在setPadding(left,
top, right, bottom)


@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view,int padding){
   view.setPadding(padding,
                   view.getPaddingTop(),
                   view.getPaddingRight(),
                   view.getPaddingBottom());
}


接受多个参数

@BindingAdapter({"bind:imageUrl","bind:error"})
public static void loadImage(ImageView view,String url,Drawable error){
   Picasso.with(view.getContext()).load(url).error(error).into(view);
}

<ImageViewapp:imageUrl=“@{venue.imageUrl}”
app:error=“@{@drawable/venueError}”/>


Binding adapter接受属性的old value

@BindingAdapter("android:paddingLeft")
publicstaticvoid setPaddingLeft(View view,int oldPadding,int newPadding){
   if(oldPadding != newPadding){
       view.setPadding(newPadding,
                       view.getPaddingTop(),
                       view.getPaddingRight(),
                       view.getPaddingBottom());
   }
}



事件处理只有一个抽象方法的接口或抽象类


@BindingAdapter("android:onLayoutChange")
publicstaticvoid setOnLayoutChangeListener(View view,View.OnLayoutChangeListener oldValue,
       View.OnLayoutChangeListener newValue){
    if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.HONEYCOMB){
        if(oldValue !=null){
            view.removeOnLayoutChangeListener(oldValue);
        }
        if(newValue !=null){
            view.addOnLayoutChangeListener(newValue);
        }
    }
}



事件处理有多个抽象方法的接口或抽象类,例如View.OnAttachStateChangeListener


@BindingAdapter("android:onViewAttachedToWindow")
public static void setListener(View view, OnViewAttachedToWindow attached) {
    setListener(view, null, attached);
}

@BindingAdapter("android:onViewDetachedFromWindow")
public static void setListener(View view, OnViewDetachedFromWindow detached) {
    setListener(view, detached, null);
}

@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"})
public static void setListener(View view, final OnViewDetachedFromWindow detach,
        final OnViewAttachedToWindow attach) {
    if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
        final OnAttachStateChangeListener newListener;
        if (detach == null && attach == null) {
            newListener = null;
        } else {
            newListener = new OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View v) {
                    if (attach != null) {
                        attach.onViewAttachedToWindow(v);
                    }
                }

                @Override
                public void onViewDetachedFromWindow(View v) {
                    if (detach != null) {
                        detach.onViewDetachedFromWindow(v);
                    }
                }
            };
        }
        final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view,
                newListener, R.id.onAttachStateChangeListener);
        if (oldListener != null) {
            view.removeOnAttachStateChangeListener(oldListener);
        }
        if (newListener != null) {
            view.addOnAttachStateChangeListener(newListener);
        }
    }
}



Converters
  Object Conversions 对象转换

<TextView   android:text='@{userMap["lastName"]}'/>


userMap返回的对象,会传进setText(CharSequence)方法当为参数
  Custom Conversions
当@{}返回的类型和android属性需要类型不一样时,可以是Conversions进行转换

<Viewandroid:background="@{isError ? @color/red : @color/white}"/>


在binding activity添加下面代码


@BindingConversion

publicstaticColorDrawable convertColorToDrawable(int color){
   returnnewColorDrawable(color);
}


不允许混合类型

<Viewandroid:background="@{isError ? @drawable/error : @color/white}"/>


Android Studio Support for Data Binding

Syntax highlighting
Flagging of expression language syntax errors
XML code completion
References, including navigation (such as navigate
to a declaration) and quick documentation

<TextViewandroid:text="@{user.username, default=测试}"/> 提供默认值


参考资源
    http://blog.csdn.net/johnny901114/article/details/50706329

    https://www.aswifter.com/2015/07/09/android-data-binding-3/

    http://www.jianshu.com/p/b1df61a4df77

    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0603/2992.html

    http://blog.csdn.net/jmq_0000/article/details/46658765

    http://www.open-open.com/lib/view/open1433580995390.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Data Binding