current position:Home>Android jetpack series -- 4 How to use databinding

Android jetpack series -- 4 How to use databinding

2022-01-26 23:30:14 Jinyang

Definition

  • Data binding , Make data objects and xml Layout binding , Support for two-way binding , yes Android Team implementation MVVM An approach to architecture ;

advantage

  1. Save a lot of template code :findViewById,onClickListener,setText etc. ;
  2. send view Decoupling from logic , Don't ask MVC So chaotic , You don't have to ask MVP That defines a lot of interfaces ;
  3. view Two way binding with data objects , Development only needs to focus on data objects , It doesn't matter view Various operations of ;
  4. xml Simple logic can be completed in ( Try not to xml To implement logic );

Easy to use

  1. Turn on DataBinding Support , stay module Of build.gradle Add the following code and sync project;
android {
    ...
    dataBinding {
        enabled = true
    }
}
 Copy code 
  1. Create a data class ArticleItem.kt
data class ArticleItem(val title:String, val author:String,val content:String,)
 Copy code 
  1. Create a Activity, And automatically generate layout , Move the cursor to the root... In the layout file View On , Press alt+enter, Select... From the pop-up menu 「Convert to data binding layout」, The code is as follows :
<?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">

    // stay data The tag declares the variables to be used 、 Full path of class 
    <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"
            // adopt @{articleInfo.title} It can be for textView Introduce the corresponding variable , You can also use default Set the default value 
            android:text="@{articleInfo.title,default=DataBinding The use of, }"
            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= That is, data binding makes data objects and xml Layout binding supports bidirectional binding Android Team implementation MVVM An approach to architecture }"
            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>

//  For convenience ArticleItem Reuse of , It can also be used. import Mode introduction 
<data>
    <import type="com.jinyang.jetpackdemo.bean.ArticleItem"/>
    <variable
        name="articleInfo"
        type="ArticleItem" />
</data>

//  To prevent repetition, you can also import Add alias 
<data>
    <import
        alias="ArticleInfo"
        type="com.jinyang.jetpackdemo.bean.ArticleItem" />
    <variable
        name="articleInfo"
        type="ArticleInfo" />
</data>
//binding By default, the name of the class is generated after the layout file name is changed to the hump naming method, such as :ActivityArticleListBinding
// You can customize  ViewDataBinding  Instance name of 
<data class="ArticleListBinding">
    ...
</data>
 Copy code 
  1. stay Activity In Chinese, it means articleInfo assignment
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 series "," Jinyang ",
            "Jetpack  It's a suite of multiple libraries ;\n" +
                    " It mainly includes architecture (Architecture)、 Basics (Foundation)、 Behavior (Behavior) 、 Interface (UI) Four aspects ;")
    }
}

//DataBinding Also support in Fragment and RecyclerView Use in 
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    binding = DataBindingUtil.inflate(inflater, getContentViewId(), container, false);
    return binding.getRoot();
}
 Copy code 

One way data binding

  • By default , Ordinary functions and strings are unobservable , That means , When you need to use them in a data binding layout , You can only get their values when you create them , But in subsequent operations , But we can't get the corresponding data .
  • Observable There are three implementations :BaseObservable、ObservableField、ObservableCollection

BaseObservable

  • BaseObservable Provides notifyChange()( Refresh all value fields ) and notifyPropertyChanged()( Update only the corresponding BR, The BR By annotating @Bindable Generate ) Two methods ;
//1.  Customize 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 Create a click event to call ArticleItem2 Of set Method 
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 series ", " Jinyang ",
            "Jetpack  It's a suite of multiple libraries ;"
        )
        // You can set the listener to observe changes in properties 
        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 add button And call the click event 
<?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 The use of, }"
            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= That is, data binding makes data objects and xml Layout binding supports bidirectional binding Android Team implementation MVVM An approach to architecture }"
            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>
 Copy code 

ObservableField

  • Inherit BaseObservable Higher limit , need notify operation , For ease of use, you can use ObservableField;
  • It's official BaseObservable Encapsulation of operations such as annotation and refresh of fields in ;
  • The official native provides encapsulation of basic data types , for example ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble as well as ObservableParcelable ;
  • Can also pass ObservableField Generic to declare other types
//1.  Define data classes 
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.  modify OnClickPresenter Code 
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")
    }
}
 Copy code 

ObservableCollection

  • dataBinding Wrapper classes are also provided to replace native List and Map, Namely ObservableList and ObservableMap
//1.  modify variable label 
<data >
    <variable
        name="articleInfo"
        type="androidx.databinding.ObservableMap&lt;String,String&gt;" />
    <variable
        name="onClickPresenter"
        type="com.jinyang.jetpackdemo.activity.ArticleListActivity.OnClickPresenter" />
</data>
//2.  modify Activity The code in 
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 series ")
            put("author", " Jinyang ")
            put("content", "Jetpack  It's a suite of multiple libraries ;")
        }

        binding.articleInfo = articleInfo
        binding.onClickPresenter = OnClickPresenter()
    }

    inner class OnClickPresenter {
        fun changeTitle() {
            articleInfo["title"]+="1"
        }

        fun changeAuthor() {
            articleInfo["author"]+="1"
        }

        fun changeContent() {
            articleInfo["content"]+="1"
        }
    }
}
 Copy code 

Two way data binding

  • Refresh the view when the data changes , When the view changes, the data can also be changed at the same time
  • The way to bind variables is an equal sign more than one-way binding , The code is as follows :
<EditText
    android:id="@+id/edit_content"
    android:layout_width="match_parent"
    android:text="@={articleInfo.content}"
    android:layout_height="wrap_content"/>
 Copy code 

LiveData Replace Observable Fields

  • It says Observable Fields, however google It is more recommended to use LiveData Replace Observable Field;
  • Reference resources google Official article Use... In two steps LiveData Replace Observable Field
  • LiveData Can sense the life cycle , This is related to Observable Fields It's not much of an advantage , because Data Binding You can check the activity of the view .

So for LiveData Come on , Its advantage is that it not only supports Transformations, And it can work with many architecture components ( Such as Room、WorkManager) Use with each other . Sum up , We recommend that you use LiveData. The method is very simple , There are only two steps .

//1.  use  LiveData  Replace  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.  Set up  LiveData  The lifecycle owner of (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)

        // The binding class of the view contains a  setLifecycleOwner  Method , Want to see from the data binding layout  LiveData , This method has to be used .
        binding.lifecycleOwner = this

        articleInfo = ArticleItem4(
            "Android Jetpack series ", " Jinyang ",
            "Jetpack  It's a suite of multiple libraries ;"
        )
        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"
        }
    }
}
 Copy code 

Event binding

  • Event binding is also a variable binding , It's just that the set variable is the callback interface , And in our example above button Click events have been useful to
//1.  Define the event method 
inner class OnClickPresenter {
    fun changeTitle(articleInfo:ArticleItem4) {
        articleInfo.title.value+="6"
    }

    fun changeAuthor() {
        articleInfo.author.value+="6"
    }
}
//2. data I quote 
<data >
    <variable
        name="articleInfo"
        type="com.jinyang.jetpackdemo.bean.ArticleItem4" />
    <variable
        name="onClickPresenter"
        type="com.jinyang.jetpackdemo.activity.ArticleListActivity.OnClickPresenter" />
</data>
//3. view In the binding 
<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()}"
    />
 Copy code 

BindingAdapter and BindingConversion

BindingAdapter

  • dataBinding Provides BindingAdapter This annotation is used to support custom attributes , Or modify the original properties ;
  • Annotation values can be existing xml attribute , for example android:src、android:text etc. , You can also customize the properties and then xml Use in ;
  • example 1: For each Button All text should be suffixed :“-Button”
//1.  Define a method , Similar to extension function 
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 series ", " Jinyang ",
            "Jetpack  It's a suite of multiple libraries ;"
        )
        binding.articleInfo = articleInfo
    }
}

@BindingAdapter("android:text")
fun setText(view: Button, text: String) {
    view.text = "$text-Button"
}

//2. xml Set in 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)}"
    />
 Copy code 
//1.  add to coil rely on 
implementation("io.coil-kt:coil:1.1.1")
//2.  Create auxiliary data classes 
class ImageBean(url: String) {
    var url: MutableLiveData<String> = MutableLiveData<String>().apply { value = url }
}
//3. Define methods and add annotations 
@BindingAdapter("url")
fun loadImage(view: ImageView, url: String) {
    view.load(url)
    LjyLogUtil.d("url:${url}")
}
//4. xml I quote 
<variable
    name="image"
    type="com.jinyang.jetpackdemo.bean.ImageBean" />
//5. ImageView Use in 
 <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 Code 
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 series ", " Jinyang ",
            "Jetpack  It's a suite of multiple libraries ;"
        )
        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"
        }
    }

}
 Copy code 

BindingConversion

  • dataBinding It also supports data conversion , Or type conversion
@BindingConversion
fun convertStringToDrawable(str: String): Drawable {
    return when (str) {
        " Red " -> {
            ColorDrawable(Color.parseColor("#FF4081"))
        }
        " Blue " -> {
            ColorDrawable(Color.parseColor("#3F51B5"))
        }
        else -> {
            ColorDrawable(Color.parseColor("#344567"))
        }
    }
}

@BindingConversion
fun convertStringToColor(str: String): Int {
    return when (str) {
        " Red " -> {
            Color.parseColor("#FF4081")
        }
        " Blue " -> {
            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='@{" Blue "}'
    android:textColor='@{" Red ",[email protected]/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='@{" Blue "}'
    android:textColor='@{" Red "}'
    android:text="author+1"
    android:onClick="@{()->onClickPresenter.changeAuthor()}"
    />
 Copy code 

Bind list data

  • RecyclerView Use BaseRecyclerViewAdapterHelper+DataBinding
  1. Customize 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)
    }
}

// Abreast of the times BaseQuickAdapter The above customization is provided ViewHolder The implementation of the ,BaseDataBindingHolder, It can be used as follows :
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()
    }
}
 Copy code 
  1. layout_item_article.xml 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">

    <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>

 Copy code 
  1. Activity The code is as follows
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")
        }
    }
}
 Copy code 
  1. activity_article_list2.xml The layout is as follows
<?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>
 Copy code 

I'm Jinyang , If you want to upgrade and learn more about dry goods , Welcome to WeChat official account. “ Jinyang said ” Receive my latest articles

copyright notice
author[Jinyang],Please bring the original link to reprint, thank you.
https://en.cdmana.com/2022/01/202201262330129900.html

Random recommended