标签归档:DataBinding

搞定Android DataBinding-01

搞定Android DataBinding-00主要是变量的绑定,如果需要加载图片,怎么办呢?
实际上,绑定变量的时候调用的是setter方法(TextView的”android:text”就是调用setText(String)),那么就应该支持绑定到自己指定的方法。

BindingAdapter

绑定一个下载图片的方法:需要图片URL和ImageView来显示,让这个方法能直接调用,最简单的就先定义为static

    @BindingAdapter({"imageUrl"})
    public static void imageLoader(ImageView imageView, String url) {
        Picasso.with(imageView.getContext()).load(url).into(imageView);
    }

绑定了上面的方法,当一个ImageView设置了”imageUrl”属性,就会调用imageLoader()方法。

BindingAdapter 属性

这样定义好之后,就可以图片下载了。

    <ImageView 
        android:layout_margin="@dimen/activity_horizontal_margin" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center" 
        android:scaleType="centerInside" 
        app:imageUrl='@{imgUrl ?? "http://0v7.jpg"}'/>

BindingAdapter 再加个参数

当加载文件失败的时候,使用失败的Drawable。
参数的顺序要一致:
{“imageUrl”, “error”}
(ImageView imageView, String url, Drawable error)

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

    }

BindingAdapter 参数属性

ImageView定义的属性,可以用来当作imageLoader的函数参数。

    <ImageView 
        android:layout_margin="@dimen/activity_horizontal_margin" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:layout_gravity="center" 
        android:scaleType="centerInside" 
        app:imageUrl='@{imgUrl ?? "http://0v7.jpg"}'
        app:error="@{@drawable/ic_image_load_error}"/>

几个方法说明

带ID的view可以直接访问

带ID的view可以直接访问,会生成public final成员。

    //布局文件中
    <Button android:id="@+id/btn_change_image" .../>
    //Binding.java 中
    public final Button btnChangeImage;

完全可以替代Butter Knife

    mBinding.btnChangeImage.setOnClickListener(this);

资源文件的引用

大多数资源文件都可以使用,不过theme、style还好像不行。

//可以使用的
@stringArray,@intArray,@typedArray,
@animator,@stateListAnimator,@color,@colorStateList
//属性使用单引号['],表达式中使用双引号["]:
bind:actInfo='@{map["change_color"]}'
//属性值使用双引号["],表达式中使用["] = &quot; 或者反引号[`]
bind:actInfo="@{map[&quot;change_image&quot;]}"
bind:actInfo="@{map[`activity_c`]}"

源码

GitHub地址:AndroidDataBindingTutorial

搞定Android DataBinding-00

最近才开始使用DataBinding,一发不可收拾。DataBinding可完成很多以前比较重复的事情,势必越来越流行。
怎么样算掌握了一个技术呢:如果你能综合所学知识,思考出合适的“方案”来实现功能,那么才算掌握了。

准备工作

Android Studio 2.0 和 Gradle 2.0.0

buildscript {
    ...
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0'
    }
}

在需要使用dataBinding的项目和library的build.gradle中开启:

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

DataBinding是什么

设置一个TextView的内容需要两步:

    mTvContent = (TextView) view.findViewById(R.id.tv_content);
    mTvContent.setText("Hello World");

在一个元素多的界面,会需要大量的重复这两步,重复的事情不是程序该做的么。
于是Butter Knife简化了第一步,然而DataBinding更进一步,来简化这个过程。

    ...
    android:text="@{textContent}"
    ...
    mBinding.setTextContent("Hello World");
    ...

通过setTextContent直接设置,元素多的界面,可以通过一个复杂对象来搞定。Data Binding可以让部分逻辑处理在layout中完成。
ps:dataBinding 支持Android 2.1 (API level 7+)

DataBinding做一个修改字体颜色的功能

Data Binding 布局文件:change_txt_color.xml

布局文件必须两部分:data 和 ViewGroup
设置字体的颜色需要一个变量:txtColor, int 类型

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable name="txtColor" type="int"/>
    </data>

    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal">

        <TextView android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="@dimen/activity_horizontal_margin" android:textColor="@{txtColor != 0 ? txtColor : @color/colorPrimary}" android:text="DataBinding Color"/>

        <Button android:id="@+id/btn_change_color" android:layout_gravity="center_vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/activity_horizontal_margin" android:text="Change Color"/>

    </LinearLayout>

</layout>

Data Binding 数据内容

需要拿到Data Binding 布局文件中的两部分内容,然后设置数据。
Data Binding 布局文件会被Android Studio自动编译成文件名+Binding的class,这里会生成:ChangeTxtColorBinding.java

    private ChangeTxtColorBinding mBinding;

    @Override
    public void init(Bundle savedInstanceState) {
        //在Activity中:dataBinding + setContentView()
        mBinding = DataBindingUtil.setContentView(this, R.layout.change_txt_color);
        //下一节再讲
        mBinding.btnChangeColor.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //直接修改颜色值
        mBinding.setTxtColor(getRandomColor());
    }

ChangeTxtColorBinding是什么样的

自动生成的java文件在:/build/intermediates/classes/debug/com.github.captain_miao.databinding.tutorial.databinding
ChangeTxtColorBinding[抽取的代码]中生成了TextView 和 mTxtColor变量。
其实原理很简单了,就是把那两步操作自动生成代码来完成了。

public class ChangeTxtColorBinding extends android.databinding.ViewDataBinding  {
    ...
    private final android.widget.TextView mboundView1;
    // variables
    private int mTxtColor;

    public boolean setVariable(int variableId, Object variable) {
        switch(variableId) {
            case BR.txtColor :
                setTxtColor((int) variable);
                return true;
        }
        return false;
    }

    public void setTxtColor(int txtColor) {
        this.mTxtColor = txtColor;
        synchronized(this) {
            mDirtyFlags |= 0x1L;
        }
        super.requestRebind();
    }
    public int getTxtColor() {
        return mTxtColor;
    }
    ...
}

几个方法说明

1. ChangeTxtColorBinding

    ChangeTxtColorBinding mBinding = DataBindingUtil.setContentView(this, R.layout.change_txt_color);

返回ChangeTxtColorBinding,并把R.layout.change_txt_color的view内容设置为Activity’s content view
等同于

    mBinding = ChangeTxtColorBinding.inflate(getLayoutInflater());
    setContentView(mBinding.getRoot());

2. setTxtColor

    mBinding.setTxtColor(getRandomColor());
    //or
    mBinding.setVariable(BR.txtColor, getRandomColor());

源码

GitHub地址:AndroidDataBindingTutorial