DataBinding详解

一、开启DataBinding

//在build.gradle文件添加
android{
   dataBinding{
      enabled true
   }
}

二、生成DataBinding布局

1、光标在布局文件的根布局-->点击Alt + Enter-->点击 “Convert to data binding layout

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

    <data>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="100dp"
            android:layout_height="100dp"/>
    </LinearLayout>
</layout>

2、创建数据类

class Test{
    var aa = "aaaaa"
    var background: Int = 0
}

3、在data中声明变量及类全名

<data>
     <variable
          name="test"
          type="com.lpf.myapplication.Test" />
</data>

4、可以通过导包方式简化类全路径;重名类通过设置别名导包

<data>
     <import type="com.lpf.myapplication.Test"/>
     <import 
          alias="TestAbc"
          type="com.abc.content.Test"/>

     <variable
          name="test1"
          type="Test" />
     <variable
          name="test2"
          type="TestAbc" />
</data>

5、通过@{test1.aa}使用变量;通过@{@{test.aa,default=12345}设置默认值(默认值无需加引号,且只在预览视图显示)

<TextView
     android:layout_width="100dp"
     android:layout_height="100dp"
     android:text="@{test1.aa}"
     android:textSize="18sp"
     android:background="@{test1.background}"/>

<TextView
     android:layout_width="100dp"
     android:layout_height="100dp"
     android:text="@{test2.aa,default=12345}"
     android:textSize="18sp"/>

6、include布局

<include
    layout="@layout/layout_title"
    bind:test="@{test}"/>

//layout_title.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="test"
            type="com.hualala.myapplication.Test" />
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{test.aa}"/>
    </LinearLayout>
</layout>

7、DataBinding不支持merge标签

三、设置数据

1、在activity中使用(DataBinding布局都会自动生成绑定类,其中绑定类命名规则:布局文件名首字母大写且省去下划线+Binding)

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
    val test = Test()
    test.aa = "aaaa"
    test.background = ContextCompat.getColor(this, R.color.colorAccent)
    dataBinding.test = test
}

注:另外绑定类还可以直接通过控件id获取控件

2、在fragment中使用

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val testFragmentBinding = DataBindingUtil.inflate<TestFragmentBinding>(inflater, R.layout.test_fragment, container, false)
    return testFragmentBinding.root
}

3、recyclerview中使用

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
    //通过id获取recyclerview
    dataBinding.recyclerViewId.layoutManager = LinearLayoutManager(this)
    dataBinding.recyclerViewId.adapter = TestAdapter()
}



class TestAdapter : RecyclerView.Adapter<TestAdapter.TestViewHolder>(){
    private val testList = arrayListOf<Test>()

    init {
        for (i in 1..5){
            val test = Test()
            test.aa = "第{$i}条"
            testList.add(test)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestViewHolder {
        val binding = DataBindingUtil.inflate<ItemTestBinding>(LayoutInflater.from(parent.context), R.layout.item_test, parent, false)
        return TestViewHolder(binding)
    }

    override fun getItemCount(): Int {
        return testList.size
    }

    override fun onBindViewHolder(holder: TestViewHolder, position: Int) {
        holder.mBinding.test = testList[position]
    }


    class TestViewHolder(binding: ItemTestBinding) : RecyclerView.ViewHolder(binding.root) {
        val mBinding: ItemTestBinding = binding
    }
}

四、数据绑定

基本类型ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble 以及 ObservableParcelable ,也可通过 ObservableField 泛型来申明其他类型,还可以通过ObservableArrayList、ObservableArrayMap使用集合类型。其中“@={test.aa}”可以实现双向绑定。

class Test{
    val aa = ObservableField<String>()
    val bb = ObservableInt()
    val cc = ObservableArrayMap<String, Drawable>()
}
object MapKey {
    const val background = "background"
}
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
    var test = Test()
    dataBinding.test = test
    test.aa.set("标题")
    test.bb.set(ContextCompat.getColor(this, R.color.colorAccent))
    test.cc[MapKey.background] = ContextCompat.getDrawable(this, R.drawable.ic_launcher_background)
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="test"
            type="com.hualala.myapplication.Test" />
        <variable
            name="key"
            type="com.hualala.myapplication.MapKey" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{test.aa}"
            android:textColor="@{test.bb}"
            android:background="@{test.cc[key.background]}"/>
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@={test.aa}"/>
    </LinearLayout>
</layout>

五、事件绑定

方法参数和原生事件参数一致可以使用"@{presenter::onClickOne}",不一致可以通过Lambda表达式"@{()-> presenter.onClickTwo(test)}"

class MainPresenter {

    fun onClickOne(view: View){
        Toast.makeText(view.context, "11111", Toast.LENGTH_SHORT).show()
    }

    fun onClickTwo(test: Test){
        Log.i("aa", "*******${test.aa.get()}")
    }
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="test"
            type="com.hualala.myapplication.Test" />
        <variable
            name="presenter"
            type="com.hualala.myapplication.MainPresenter" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{test.aa}"
            android:onClick="@{presenter::onClickOne}"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{test.aa}"
            android:onClick="@{()-> presenter.onClickTwo(test)}"/>
    </LinearLayout>
</layout>
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val dataBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        var test = Test()
        dataBinding.presenter = MainPresenter()
        dataBinding.test = test
        test.aa.set("按钮")
    }

六、调用静态方法

class StringUtil {
    companion object{
        @JvmStatic//需要添加该注解,否则xml中找不到该方法
        fun toUpperCase(string: String): String{
            return string.toUpperCase()
        }
    }
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <import type="com.hualala.myapplication.StringUtil"/>
        <variable
            name="test"
            type="com.hualala.myapplication.Test" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{StringUtil.toUpperCase(test.aa)}"/>
    </LinearLayout>
</layout>

七、运算符

  • 算术    +  -  /  *  %
  • 字符串合并   +
  • 逻辑    &&   ||
  • 二元    &  |  ^
  • 一元    +  -   !  ~
  • 移位    >>   >>>   <<
  • 比较    ==  >  <   >=   <=   !=
  • 三元   ?:
  • 空合并  ??      ("@{test.aa ?? test.bb}"等价于“@{test.aa!=null?test.aa:test.bb}”)

八、BindingAdapter自定义属性

1、声明属性(静态方法,kotlin需要加@JvmStatic注解)

class ImageUtil{
    companion object{
        @JvmStatic
        @BindingAdapter("url")
        fun loadImage(imageView: ImageView, url: String){
            Log.e("aa", "*********$url")
        }
    }
}

注:check that the adapter is annotated correctly and that the parameter type matches异常,需要在build.gradle中添加apply plugin: 'kotlin-kapt' 

2、引用属性(bind可以自定义)

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto">

    <data>
        <import type="com.hualala.myapplication.ImageUtil"/>
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            bind:url='@{"http://test.png"}'/>
    </LinearLayout>
</layout>

注:包含字符串外层需要用单引号,如 android:text='@{"字符串"}'

九、BindingConversion数据转换

同类型转换,如conversionString添加前缀;不同类型转换如conversionStringToDrawable

object ImageUtil{
    @JvmStatic
    @BindingAdapter("url")
    fun loadImage(imageView: ImageView, url: String){
        Log.e("aa", "*********$url")
    }

    //同类型转换
    @JvmStatic
    @BindingConversion
    fun conversionString(str: String): String{
        return "http://$str"
    }

    //不同类型转换
    @JvmStatic
    @BindingConversion
    fun conversionStringToDrawable(str: String): Drawable{
        return ColorDrawable(Color.parseColor(str))
    }
}
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:bind="http://schemas.android.com/apk/res-auto">

    <data>
        <import type="com.hualala.myapplication.ImageUtil"/>
        <variable
            name="test"
            type="com.hualala.myapplication.Test" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background='@{"#FF0000"}'>
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            bind:url='@{"test.png"}'/>
    </LinearLayout>
</layout>

注:

(1)@BindingConversion比@BindingAdapter先执行

(2)@BindingConversion使用companion object方式定义静态方法,会报异常@BindingConversion is only allowed on public static methods conversionString(String),采用Object方式定义静态方法即可

十、资源引用

<resources>
    <string name="test_to_test">%s to %s</string>
</resources>
<TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text='@{@string/test_to_test("a","b")}'/>

猜你喜欢

转载自blog.csdn.net/yufumatou/article/details/113571917