美文网首页
Jetpack学习(二) 数据绑定

Jetpack学习(二) 数据绑定

作者: 飞哥278999401 | 来源:发表于2021-03-31 22:30 被阅读0次

    一、配置

    在应用的build.gradle里面加上

    android {
    
    '''
        dataBinding {
            enabled = true
        }
    '''
    }
    

    二、布局和绑定表达式

    1、建立实体类User

    data class User(val firstName: String, val lastName: String)
    

    2、xml布局文件,数据绑定布局文件,以根标记 layout 开头,后跟 data 元素和 view 根元素。

    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable name="user" type="com.example.myapplication.entity.User"/>
        </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="@{user.firstName}" />
        </LinearLayout>
    </layout>
    
    3、绑定数据
    a、activity中使用,ActivityMainBinding是自动生成的,根据基于布局文件的名称,比如布局文件名为 activity_main.xml,因此生成的对应类为 ActivityMainBinding。

    如果实在找不到,可以在java(generated)查看


    image.png
     val binding: ActivityMainBinding = DataBindingUtil.setContentView(
                    this, R.layout.activity_main)
    
    b、如果在fragment、listview、recyclerview中使用,可以使用DataBindingUtil.inflate
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
    
            val fragmentOneBinding = DataBindingUtil.inflate<FragmentOneBinding>(layoutInflater,R.layout.fragment_one,container,false);
            fragmentOneBinding.user = User("zhang","san");
            return fragmentOneBinding.root;
        }
    
    
    
    

    4、表达式语言

    算术运算符 + - / * %
    字符串连接运算符 +
    逻辑运算符 && ||
    二元运算符 & | ^
    一元运算符 + - ! ~
    移位运算符 >> >>> <<
    比较运算符 == > < >= <=(请注意,< 需要转义为 <)
    instanceof
    分组运算符 ()
    字面量运算符 - 字符、字符串、数字、null
    类型转换
    方法调用
    字段访问
    数组访问 []
    三元运算符 ?:

    android:text="@{String.valueOf(index + 1)}"
    android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
    android:transitionName='@{"image_" + id}'
    

    5、事件处理

    a、方法引用
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <data>
            <variable name="user" type="com.example.myapplication.entity.User"/>
            <variable name="handler" type="com.example.myapplication.fragment.OneFragment"/>
        </data>
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView android:layout_width="wrap_content"
                android:id="@+id/text_tv"
                android:layout_height="wrap_content"
                android:text="@{user.firstName}"
                android:onClick="@{handler.testClick}"
                />
        </LinearLayout>
    </layout>
    
    class OneFragment : Fragment() {
    
        fun testClick(view: View){
    
           Log.d("hah","hahaha"+view.toString());
    
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
    
            val fragmentOneBinding = DataBindingUtil.inflate<FragmentOneBinding>(layoutInflater,R.layout.fragment_one,container,false);
            fragmentOneBinding.user = User("zhang","san");
            fragmentOneBinding.handler = this;
            return fragmentOneBinding.root;
        }
    
    }
    

    注意fragmentOneBinding.handler = this;这一句话不要漏掉

    b、监听器绑定

    监听器绑定是在事件发生时运行的绑定表达式。它们类似于方法引用,允许运行任意数据绑定表达式。

     fun testClick1(user:User){
            
            Log.d("hah","hahaha"+user);
            
     }
    
      <TextView android:layout_width="wrap_content"
                android:id="@+id/text_tv"
                android:layout_height="wrap_content"
                android:text="@{user.firstName}"
                android:onClick="@{()->handler.testClick1(user)}"
                />
    

    如果要把点击的view也传递过去,需要

      fun testClick2(view: View,user:User){
            Log.d("hah","hahaha"+user+view.toString());
        }
    
            <TextView
                android:id="@+id/text_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{(view)->handler.testClick2(view,user)}"
                android:text="@{user.firstName}" />
    
    

    6、使用可观察的数据对象

    可观察性是指一个对象将其数据变化告知其他对象的能力。通过数据绑定库,您可以让对象、字段或集合变为可观察。可观察类有三种不同类型:对象、字段、集合

    • ObservableBoolean
    • ObservableByte
    • ObservableChar
    • ObservableShort
    • ObservableInt
    • ObservableLong
    • ObservableFloat
    • ObservableDouble
    • ObservableParcelable
    可观察字段

    可观察字段是具有单个字段的自包含可观察对象。原语版本避免在访问操作期间封箱和开箱。如需使用此机制,创建只读属性

        class User {
            val firstName = ObservableField<String>()
            val lastName = ObservableField<String>()
            val age = ObservableInt()
        }
    
           user.firstName.set("dddd");
           Log.d("haha",user.firstName.get()!!);
    
    可观察集合
         val map = ObservableArrayMap<String, Any>().apply {
            put("firstName", "Google")
            put("lastName", "Inc.")
            put("age", 17)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
    
            val fragmentOneBinding = DataBindingUtil.inflate<FragmentOneBinding>(
                layoutInflater,
                R.layout.fragment_one,
                container,
                false
            );
            fragmentOneBinding.user = map;
    
            return fragmentOneBinding.root;
        }
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            map.put("firstName","hhhhhhh")
        }
    
    
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    
        <data>
    
            <import type="androidx.databinding.ObservableMap"/>
            <variable name="user" type="ObservableMap&lt;String, Object>"/>
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <TextView
                android:id="@+id/text_tv"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.firstName}" />
        </LinearLayout>
    </layout>
    

    不要忘记 fragmentOneBinding.user = map;

    c、绑定适配器

    可以给一类操作命名直接在xml里面调用

    比如,我有Imageview,实际每次都是传入Url加载进控件

    在app的gradle里面添加

    plugins {
        id 'kotlin-kapt'
    }
    

    定义一个object类,例如

    object ImageUtil {
    
        @BindingAdapter("imageurl")
        @JvmStatic
        fun loadImage(view: ImageView, url: String) {
           Glide.with(imageview).load(url).into(imageview)
        }
    }
    

    在布局文件里使用

     <ImageView
                android:id="@+id/haha"
                imageurl="@{user.profileUrl}"
                android:layout_width="200dp"
                android:layout_height="200dp" />
    
    

    @BindingAdapter("imageurl")的imageurl对应布局文件里面控件的imageurl,布局文件传入的字符串会调用到被@BindingAdapter("imageurl")注解的方法。

    注意:被@BindingAdapter注解的方法必须为static方法,并且要加@JvmStatic注解,不然会报错,如下

    java.lang.IllegalStateException: Required DataBindingComponent is null in class FragmentOneBindingImpl. A BindingAdapter in com.example.myapplication.fragment.ImageUtil is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.

    相关文章

      网友评论

          本文标题:Jetpack学习(二) 数据绑定

          本文链接:https://www.haomeiwen.com/subject/qeqnhltx.html