美文网首页kotlinAndroidAndroid技术
Android Jetpack系列--4.DataBinding

Android Jetpack系列--4.DataBinding

作者: 今阳说 | 来源:发表于2021-08-30 09:02 被阅读0次

    定义

    • 即数据绑定,使数据对象和xml布局绑定,支持双向绑定,是Android团队实现MVVM架构的一种方法;

    优点

    1. 省去大量模板代码:findViewById,onClickListener,setText等;
    2. 使view与逻辑解耦,不用向MVC那样混乱,也不用向MVP那样定义大量接口;
    3. view与数据对象双向绑定,开发时只需关注数据对象,无需关系view的各种操作;
    4. xml中可以完成简单逻辑(尽量不要在xml中实现逻辑);

    简单使用

    1. 开启DataBinding支持,在module的build.gradle中加入下面代码并sync project;
    android {
        ...
        dataBinding {
            enabled = true
        }
    }
    
    1. 创建一个数据类ArticleItem.kt
    data class ArticleItem(val title:String, val author:String,val content:String,)
    
    1. 创建一个Activity,并自动生成布局,在布局文件中将光标移动到根View上,按alt+enter,选择弹出菜单的「Convert to data binding layout」,代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">
    
        //在data标签当中声明要使用到的变量、类的全路径
        <data>
            <variable
                name="articleInfo"
                type="com.jinyang.jetpackdemo.bean.ArticleItem" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:context=".activity.ArticleListActivity">
    
            <TextView
                android:id="@+id/tv_article_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                //通过@{articleInfo.title}可以为textView引入对应的变量,还可以用default设置默认值
                android:text="@{articleInfo.title,default=DataBinding使用详解}"
                android:textColor="#000000"
                android:textSize="20sp"
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/tv_article_author"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{articleInfo.author,default=JinYang}"
                android:textColor="#666666"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_title" />
    
            <TextView
                android:id="@+id/tv_article_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="2"
                android:text="@{articleInfo.content,default=即数据绑定使数据对象和xml布局绑定支持双向绑定是Android团队实现MVVM架构的一种方法}"
                android:textColor="#333333"
                android:textSize="18sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_author" />
    
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    
    // 为方便ArticleItem的复用,也可以用import方式引入
    <data>
        <import type="com.jinyang.jetpackdemo.bean.ArticleItem"/>
        <variable
            name="articleInfo"
            type="ArticleItem" />
    </data>
    
    // 为防止重复还可以为import增加别名
    <data>
        <import
            alias="ArticleInfo"
            type="com.jinyang.jetpackdemo.bean.ArticleItem" />
        <variable
            name="articleInfo"
            type="ArticleInfo" />
    </data>
    //binding类的名称默认是已布局文件名改完驼峰命名法生成的如:ActivityArticleListBinding
    //可以通过如下方式自定义 ViewDataBinding 的实例名
    <data class="ArticleListBinding">
        ...
    </data>
    
    1. 在Activity中为articleInfo赋值
    class ArticleListActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    <!--         val binding: ArticleListBinding = -->
            val binding: ActivityArticleListBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list)
            binding.articleInfo= ArticleItem("Android Jetpack系列","今阳",
                "Jetpack 是一个由多个库组成的套件;\n" +
                        "主要包括架构(Architecture)、基础(Foundation)、行为(Behavior) 、界面(UI)四个方面;")
        }
    }
    
    //DataBinding也支持在Fragment和RecyclerView中使用
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        binding = DataBindingUtil.inflate(inflater, getContentViewId(), container, false);
        return binding.getRoot();
    }
    

    单向数据绑定

    • 默认情况下,普通函数和字符串是不可观察的,这就意味着,当您在数据绑定布局中需要使用它们时,只能在新建的时候获取它们的值,但在后续的操作中,却不能得到相应的数据。
    • Observable有三种实现:BaseObservable、ObservableField、ObservableCollection

    BaseObservable

    • BaseObservable 提供了 notifyChange()(刷新所有的值域)和 notifyPropertyChanged()(只更新对应 BR,该BR通过注释 @Bindable 生成)两个方法;
    //1. 自定义Observable
    class ArticleItem2(var title: String, author: String, content: String) :
        BaseObservable() {
    
        @get:Bindable
        var author: String = author
            set(value) {
                field = value
                notifyPropertyChanged(BR.author)
            }
    
        @get:Bindable
        var content: String = content
            set(value) {
                field = value
                notifyChange()
            }
    }
    2. Activity中创建点击事件调用ArticleItem2的set方法
    class ArticleListActivity : AppCompatActivity() {
         lateinit var articleInfo: ArticleItem2
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val binding: ActivityArticleListBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list)
            articleInfo = ArticleItem2(
                "Android Jetpack系列", "今阳",
                "Jetpack 是一个由多个库组成的套件;"
            )
            //可以设置监听器观察属性的更改
            articleInfo.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback() {
                override fun onPropertyChanged(sender: Observable, propertyId: Int) {
                    when {
                        BR.author == propertyId -> {
                            LjyLogUtil.d("BR.author")
                        }
                        BR.content == propertyId -> {
                            LjyLogUtil.d("BR.content")
                        }
                        BR._all == propertyId -> {
                            LjyLogUtil.d("BR._all")
                        }
                        else -> {
                            LjyLogUtil.d("propertyId:$propertyId")
                        }
                    }
                }
            })
            binding.articleInfo=articleInfo
            binding.onClickPresenter=OnClickPresenter()
        }
    
        inner class OnClickPresenter {
            fun changeTitle() {
                articleInfo.title="${articleInfo.title}1"
            }
            fun changeAuthor() {
                articleInfo.author="${articleInfo.author}1"
            }
            fun changeContent() {
                articleInfo.content="${articleInfo.content}1"
            }
        }
    }
    //3.xml中增加button并调用点击事件
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">
    
        <data >
            <variable
                name="articleInfo"
                type="com.jinyang.jetpackdemo.bean.ArticleItem2" />
            <variable
                name="onClickPresenter"
                type="com.jinyang.jetpackdemo.activity.ArticleListActivity.OnClickPresenter" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            tools:context=".activity.ArticleListActivity">
    
            <TextView
                android:id="@+id/tv_article_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{articleInfo.title,default=DataBinding使用详解}"
                android:textColor="#000000"
                android:textSize="20sp"
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/tv_article_author"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{articleInfo.author,default=JinYang}"
                android:textColor="#666666"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_title" />
    
            <TextView
                android:id="@+id/tv_article_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="2"
                android:text="@{articleInfo.content,default=即数据绑定使数据对象和xml布局绑定支持双向绑定是Android团队实现MVVM架构的一种方法}"
                android:textColor="#333333"
                android:textSize="16sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_author" />
    
            <Button
                android:id="@+id/btn_title"
                android:layout_width="wrap_content"
                android:text="title+1"
                android:textAllCaps="false"
                app:layout_constraintLeft_toLeftOf="parent"
                android:onClick="@{()->onClickPresenter.changeTitle()}"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_content"
                android:layout_margin="10dp"
                android:layout_height="wrap_content"/>
            <Button
                android:id="@+id/btn_author"
                android:layout_width="wrap_content"
                android:text="author+1"
                android:textAllCaps="false"
                app:layout_constraintLeft_toRightOf="@id/btn_title"
                android:layout_margin="10dp"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_content"
                android:onClick="@{()->onClickPresenter.changeAuthor()}"
                android:layout_height="wrap_content"/>
            <Button
                android:id="@+id/btn_content"
                app:layout_constraintLeft_toRightOf="@id/btn_author"
                android:onClick="@{()->onClickPresenter.changeContent()}"
                android:layout_width="wrap_content"
                android:layout_margin="10dp"
                android:text="content+1"
                android:textAllCaps="false"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_content"
                android:layout_height="wrap_content"/>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    

    ObservableField

    • 继承BaseObservable限制较高,需要notify操作,为了使用方便可以使用ObservableField;
    • 是官方对 BaseObservable 中字段的注解和刷新等操作的封装;
    • 官方原生提供了对基本数据类型的封装,例如 ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble 以及 ObservableParcelable ;
    • 也可通过 ObservableField 泛型来申明其他类型
    //1. 定义数据类
    class ArticleItem3(title: String, author: String, content: String) {
        val title: ObservableField<String> = ObservableField<String>(title)
        val author: ObservableField<String> = ObservableField<String>(author)
        val content: ObservableField<String> = ObservableField<String>(content)
    }
    //2. 修改OnClickPresenter代码
    inner class OnClickPresenter {
        fun changeTitle() {
            articleInfo.title.set("${articleInfo.title.get()}1")
        }
    
        fun changeAuthor() {
            articleInfo.author.set("${articleInfo.author.get()}1")
        }
    
        fun changeContent() {
            articleInfo.content.set("${articleInfo.content.get()}1")
        }
    }
    

    ObservableCollection

    • dataBinding 也提供了包装类用于替代原生的 List 和 Map,分别是 ObservableList 和 ObservableMap
    //1. 修改variable标签
    <data >
        <variable
            name="articleInfo"
            type="androidx.databinding.ObservableMap&lt;String,String&gt;" />
        <variable
            name="onClickPresenter"
            type="com.jinyang.jetpackdemo.activity.ArticleListActivity.OnClickPresenter" />
    </data>
    //2. 修改Activity中的代码
    class ArticleListActivity : AppCompatActivity() {
        lateinit var articleInfo: ObservableArrayMap<String, String>
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val binding: ActivityArticleListBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list)
    
            articleInfo = ObservableArrayMap()
            articleInfo.apply {
                put("title", "Android Jetpack系列")
                put("author", "今阳")
                put("content", "Jetpack 是一个由多个库组成的套件;")
            }
    
            binding.articleInfo = articleInfo
            binding.onClickPresenter = OnClickPresenter()
        }
    
        inner class OnClickPresenter {
            fun changeTitle() {
                articleInfo["title"]+="1"
            }
    
            fun changeAuthor() {
                articleInfo["author"]+="1"
            }
    
            fun changeContent() {
                articleInfo["content"]+="1"
            }
        }
    }
    

    双向数据绑定

    • 当数据改变时同时使视图刷新,而视图改变时也可以同时改变数据
    • 绑定变量的方式比单向绑定多了一个等号,代码如下:
    <EditText
        android:id="@+id/edit_content"
        android:layout_width="match_parent"
        android:text="@={articleInfo.content}"
        android:layout_height="wrap_content"/>
    

    LiveData 替换 Observable Fields

    • 上面讲了Observable Fields,但是google官方更推荐使用LiveData 替换 Observable Field;
    • 参考google官方文章两步使用 LiveData 替换 Observable Field
    • LiveData 可以感知生命周期,这一点与 Observable Fields 相比并没有多大优势,因为 Data Binding 原本就可以检查视图活跃情况。
      因此对于 LiveData 来说,它的优势在于不仅支持Transformations,而且可以与许多架构组件 (如Room、WorkManager) 相互配合使用。
      综上,我们推荐您使用 LiveData。方法也非常简单,只需要两个步骤。
    //1. 用 LiveData 替换 Observable Fields
    class ArticleItem4(title: String, author: String, content: String) : ViewModel() {
        var title: MutableLiveData<String> = MutableLiveData<String>().apply { value = title }
        var author: MutableLiveData<String> = MutableLiveData<String>().apply { value = author }
        var content: MutableLiveData<String> = MutableLiveData<String>().apply { value = content }
    }
    //2. 设置 LiveData 的生命周期所有者(lifecycleOwner)
    class ArticleListActivity : AppCompatActivity() {
        lateinit var articleInfo: ArticleItem4
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            val binding: ActivityArticleListBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list)
    
            //视图的绑定类中包含一个 setLifecycleOwner 方法,想要从数据绑定布局观察 LiveData ,必须使用该方法。
            binding.lifecycleOwner = this
    
            articleInfo = ArticleItem4(
                "Android Jetpack系列", "今阳",
                "Jetpack 是一个由多个库组成的套件;"
            )
            binding.articleInfo = articleInfo
            binding.onClickPresenter = OnClickPresenter()
        }
    
        inner class OnClickPresenter {
            fun changeTitle() {
                articleInfo.title.value+="6"
            }
    
            fun changeAuthor() {
                articleInfo.author.value+="6"
            }
    
            fun changeContent() {
                articleInfo.content.value+="6"
            }
        }
    }
    

    事件绑定

    • 事件绑定也是一种变量绑定,只不过设置的变量是回调接口而已,而且我们上面的举例中button的点击事件已有用到
    //1. 定义事件方法
    inner class OnClickPresenter {
        fun changeTitle(articleInfo:ArticleItem4) {
            articleInfo.title.value+="6"
        }
    
        fun changeAuthor() {
            articleInfo.author.value+="6"
        }
    }
    //2. data中引用
    <data >
        <variable
            name="articleInfo"
            type="com.jinyang.jetpackdemo.bean.ArticleItem4" />
        <variable
            name="onClickPresenter"
            type="com.jinyang.jetpackdemo.activity.ArticleListActivity.OnClickPresenter" />
    </data>
    //3. view中绑定
    <Button
        android:id="@+id/btn_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="title+1"
        android:onClick="@{()->onClickPresenter.changeTitle(articleInfo)}"
        />
    <Button
        android:id="@+id/btn_author"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="author+1"
        android:onClick="@{()->onClickPresenter.changeAuthor()}"
        />
    

    BindingAdapter 和 BindingConversion

    BindingAdapter

    • dataBinding 提供了 BindingAdapter 这个注解用于支持自定义属性,或者是修改原有属性;
    • 注解值可以是已有的 xml 属性,例如 android:src、android:text等,也可以自定义属性然后在 xml 中使用;
    • 例1:为每个 Button 的文本都要加上后缀:“-Button”
    //1. 定义一个方法,类似于扩展函数
    class ArticleListActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val binding: ActivityArticleListBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list)
            binding.lifecycleOwner = this
            var articleInfo: ArticleItem4 = ArticleItem4(
                "Android Jetpack系列", "今阳",
                "Jetpack 是一个由多个库组成的套件;"
            )
            binding.articleInfo = articleInfo
        }
    }
    
    @BindingAdapter("android:text")
    fun setText(view: Button, text: String) {
        view.text = "$text-Button"
    }
    
    //2. xml中设置android:text='@{"title+1"}'
    <Button
        android:id="@+id/btn_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text='@{"title+1"}'
        android:onClick="@{()->onClickPresenter.changeTitle(articleInfo)}"
        />
    
    • 例2:自定义属性
    • 这里借助一个Google 官推的图片库 Coil,这个库完全是用 Kotlin 写的,而且运用了大量 Kotlin 的特性,尤其是协程;
    • Coil 给 ImageView 加了很多拓展函数,所以我们一行代码便能进行图片加载;
    • 详细使用可以参考:还在用 Glide?看看 Google 官推的图片库 Coil 有何不同!
    //1. 添加coil依赖
    implementation("io.coil-kt:coil:1.1.1")
    //2. 创建辅助的数据类
    class ImageBean(url: String) {
        var url: MutableLiveData<String> = MutableLiveData<String>().apply { value = url }
    }
    //3.定义方法并添加注解
    @BindingAdapter("url")
    fun loadImage(view: ImageView, url: String) {
        view.load(url)
        LjyLogUtil.d("url:${url}")
    }
    //4. xml中引用
    <variable
        name="image"
        type="com.jinyang.jetpackdemo.bean.ImageBean" />
    //5. ImageView中使用
     <ImageView
        app:layout_constraintTop_toBottomOf="@+id/edit_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:src="@mipmap/ic_launcher"
        android:layout_width="wrap_content"
        app:url="@{image.url}"
        android:layout_height="wrap_content"/>
    //6. activity代码
    lass ArticleListActivity : AppCompatActivity() {
        lateinit var articleInfo: ArticleItem4
        lateinit var image: ImageBean
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val binding: ActivityArticleListBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list)
            binding.lifecycleOwner = this
            articleInfo = ArticleItem4(
                "Android Jetpack系列", "今阳",
                "Jetpack 是一个由多个库组成的套件;"
            )
            binding.articleInfo = articleInfo
            image = ImageBean("https://pic1.zhimg.com/v2-dc32dcddfd7e78e56cc4b6f689a24979_is.jpg")
            binding.image=image
            binding.onClickPresenter = OnClickPresenter()
        }
    
        inner class OnClickPresenter {
            fun changeTitle(articleInfo: ArticleItem4) {
                articleInfo.title.value += "6"
                image.url.value="https://pic3.zhimg.com/v2-e5656460688d19f7358ab3a6055fe34a_720w.jpg?source=95cc6b4a"
            }
    
            fun changeAuthor() {
                articleInfo.author.value += "6"
                image.url.value="https://pic2.zhimg.com/v2-f6981776beae87401991b426fbe34fdd_720w.jpg?source=95cc6b4a"
            }
    
            fun changeContent() {
                articleInfo.content.value += "6"
                image.url.value="https://pic2.zhimg.com/v2-f2eddc2fe0e509de5bbeeb351ddc2c61_1440w.jpg?source=172ae18b"
            }
        }
    
    }
    

    BindingConversion

    • dataBinding 还支持对数据进行转换,或者进行类型转换
    @BindingConversion
    fun convertStringToDrawable(str: String): Drawable {
        return when (str) {
            "红色" -> {
                ColorDrawable(Color.parseColor("#FF4081"))
            }
            "蓝色" -> {
                ColorDrawable(Color.parseColor("#3F51B5"))
            }
            else -> {
                ColorDrawable(Color.parseColor("#344567"))
            }
        }
    }
    
    @BindingConversion
    fun convertStringToColor(str: String): Int {
        return when (str) {
            "红色" -> {
                Color.parseColor("#FF4081")
            }
            "蓝色" -> {
                Color.parseColor("#3F51B5")
            }
            else -> {
                Color.parseColor("#344567")
            }
        }
    }
    
    <Button
        android:id="@+id/btn_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background='@{"蓝色"}'
        android:textColor='@{"红色",default=@color/colorAccent}'
        android:text="title+1"
        android:onClick="@{()->onClickPresenter.changeTitle(articleInfo)}"
        />
    <Button
        android:id="@+id/btn_author"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background='@{"蓝色"}'
        android:textColor='@{"红色"}'
        android:text="author+1"
        android:onClick="@{()->onClickPresenter.changeAuthor()}"
        />
    

    绑定列表数据

    • RecyclerView使用BaseRecyclerViewAdapterHelper+DataBinding
    1. 自定义Adapter:
    class ArticleAdapter(data: MutableList<ArticleItem4>?) :
        BaseQuickAdapter<ArticleItem4, ArticleItemViewHolder>(R.layout.layout_item_article, data) {
    
        override fun convert(holder: ArticleItemViewHolder, item: ArticleItem4) {
            holder.binding?.articleInfo = item
            holder.binding?.executePendingBindings()
        }
    
        class ArticleItemViewHolder(view: View) : BaseViewHolder(view) {
            val binding: LayoutItemArticleBinding? = DataBindingUtil.bind(view)
        }
    }
    
    //最新的BaseQuickAdapter提供了上述自定义ViewHolder的实现,BaseDataBindingHolder,可以如下使用:
    class ArticleAdapter(data: MutableList<ArticleItem4>?) :
        BaseQuickAdapter<ArticleItem4,  BaseDataBindingHolder<LayoutItemArticleBinding> >(R.layout.layout_item_article, data) {
    
        override fun convert(holder: BaseDataBindingHolder<LayoutItemArticleBinding>, item: ArticleItem4) {
            holder.dataBinding?.articleInfo = item
            holder.dataBinding?.executePendingBindings()
        }
    }
    
    1. layout_item_article.xml布局
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <data>
            <variable
                name="articleInfo"
                type="com.jinyang.jetpackdemo.bean.ArticleItem4" />
        </data>
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <TextView
                android:id="@+id/tv_article_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{articleInfo.title,default=titleText}"
                android:textColor="#000000"
                android:textSize="20sp"
                android:textStyle="bold"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/tv_article_author"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{articleInfo.author,default=authorText}"
                android:textColor="#666666"
                android:textSize="14sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_title" />
    
            <TextView
                android:id="@+id/tv_article_content"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="2"
                android:text="@{articleInfo.content,default=contentText}"
                android:textColor="#333333"
                android:textSize="16sp"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/tv_article_author" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </layout>
    
    
    1. Activity代码如下
    class ArticleList2Activity : AppCompatActivity() {
        lateinit var mAdapter:ArticleAdapter
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            LjyLogUtil.d("onCreate")
            val binding: ActivityArticleList2Binding =
                DataBindingUtil.setContentView(this, R.layout.activity_article_list2)
            binding.lifecycleOwner = this
            binding.rvArticleList.layoutManager = LinearLayoutManager(this)
            val articleList:MutableList<ArticleItem4> = ArrayList()
            articleList.add(ArticleItem4("title1","jinYang","content111"))
            articleList.add(ArticleItem4("title2","jinYang","content222"))
            articleList.add(ArticleItem4("title3","jinYang","content333"))
            mAdapter= ArticleAdapter(articleList)
            binding.rvArticleList.adapter=mAdapter
            binding.onClickPresenter2 = OnClickPresenter2()
        }
    
        inner class OnClickPresenter2 {
            fun addArticle() {
                mAdapter.addData(ArticleItem4("title${mAdapter.data.size}","jinYang","content${mAdapter.data.size}"))
                LjyLogUtil.d("addArticle")
            }
    
            fun removeArticle() {
                mAdapter.removeAt(0)
                LjyLogUtil.d("removeArticle")
            }
        }
    }
    
    1. activity_article_list2.xml布局如下
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">
        <data>
            <variable
                name="onClickPresenter2"
                type="com.jinyang.jetpackdemo.activity.ArticleList2Activity.OnClickPresenter2" />
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context=".activity.ArticleList2Activity">
            <Button
                android:id="@+id/btn_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{()->onClickPresenter2.addArticle()}"
                android:text="addArticle" />
            <Button
                android:id="@+id/btn_remove"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{()->onClickPresenter2.removeArticle()}"
                android:text="removeArticle" />
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_article_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    </layout>
    

    我是今阳,如果想要进阶和了解更多的干货,欢迎关注微信公众号 “今阳说” 接收我的最新文章

    相关文章

      网友评论

        本文标题:Android Jetpack系列--4.DataBinding

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