定義
- 即數(shù)據(jù)綁定,使數(shù)據(jù)對象和xml布局綁定,支持雙向綁定,是Android團隊實現(xiàn)MVVM架構的一種方法;
優(yōu)點
- 省去大量模板代碼:findViewById,onClickListener,setText等;
- 使view與邏輯解耦,不用向MVC那樣混亂,也不用向MVP那樣定義大量接口;
- view與數(shù)據(jù)對象雙向綁定,開發(fā)時只需關注數(shù)據(jù)對象,無需關系view的各種操作;
- xml中可以完成簡單邏輯(盡量不要在xml中實現(xiàn)邏輯);
簡單使用
開啟DataBinding支持,在module的build.gradle中加入下面代碼并sync project;
android {
...
dataBinding {
enabled = true
}
}
- 創(chuàng)建一個數(shù)據(jù)類ArticleItem.kt
data class ArticleItem(val title:String, val author:String,val content:String,)
1.1 創(chuàng)建一個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=即數(shù)據(jù)綁定使數(shù)據(jù)對象和xml布局綁定支持雙向綁定是Android團隊實現(xiàn)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.2 在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();
}
單向數(shù)據(jù)綁定
- 默認情況下,普通函數(shù)和字符串是不可觀察的,這就意味著,當您在數(shù)據(jù)綁定布局中需要使用它們時,只能在新建的時候獲取它們的值,但在后續(xù)的操作中,卻不能得到相應的數(shù)據(jù)。
- Observable有三種實現(xiàn):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中創(chuàng)建點擊事件調(diào)用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 是一個由多個庫組成的套件;"
)
//可以設置監(jiān)聽器觀察屬性的更改
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并調(diào)用點擊事件
<?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=即數(shù)據(jù)綁定使數(shù)據(jù)對象和xml布局綁定支持雙向綁定是Android團隊實現(xiàn)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 中字段的注解和刷新等操作的封裝;
- 官方原生提供了對基本數(shù)據(jù)類型的封裝,例如 ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble 以及 ObservableParcelable ;
- 也可通過 ObservableField 泛型來申明其他類型
//1. 定義數(shù)據(jù)類
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<String,String>" />
<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"
}
}
}
雙向數(shù)據(jù)綁定
- 當數(shù)據(jù)改變時同時使視圖刷新,而視圖改變時也可以同時改變數(shù)據(jù)
- 綁定變量的方式比單向綁定多了一個等號,代碼如下:
<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 相比并沒有多大優(yōu)勢,因為 Data Binding 原本就可以檢查視圖活躍情況。
因此對于 LiveData 來說,它的優(yōu)勢在于不僅支持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 方法,想要從數(shù)據(jù)綁定布局觀察 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"
}
}
}
事件綁定
- 事件綁定也是一種變量綁定,只不過設置的變量是回調(diào)接口而已,而且我們上面的舉例中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. 定義一個方法,類似于擴展函數(shù)
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 的特性,尤其是協(xié)程;
- Coil 給 ImageView 加了很多拓展函數(shù),所以我們一行代碼便能進行圖片加載;
- 詳細使用可以參考:還在用 Glide?看看 Google 官推的圖片庫 Coil 有何不同!
//1. 添加coil依賴
implementation("io.coil-kt:coil:1.1.1")
//2. 創(chuàng)建輔助的數(shù)據(jù)類
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 還支持對數(shù)據(jù)進行轉換,或者進行類型轉換
@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()}"
/>
綁定列表數(shù)據(jù)
- RecyclerView使用BaseRecyclerViewAdapterHelper+DataBinding
自定義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的實現(xiàn),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()
}
}
- 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>
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")
}
}
}
- 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>
databinding使用string format
<string name="Generic_Text">My Name is %s</string>android:text= "@{@string/Generic_Text(Profile.name)}"
多個字符串拼接的:
<string name="generic_name">字符串1: %1$s,字符串2:%2$s</string> android:text= "@{@string/generic_name(str1, str2)}"
+ 號方式
android:text="@{`字符串:` + str}"/>使用
使用Html標簽
<data> <import type="android.text.Html"/></data>... android:text="@{Html.fromHtml(@string/sxx_user_rank(user.readTimes))}"
使用過程中當兩個font標簽嵌套html內(nèi)層標簽不起作用。
普通的
android:text='@{@string/user_name+bean.name}'
這里的引號需要使用單引號
注意
特別需要注意的是,字符串的拼接不要用直接的文字表示,比如
android:text='@{"user的name:"+bean.name}'
這種容易出問題。
并且,DataBinding報錯并不會指向錯誤源,事后很難排除。
故,需采用 @string/xxxx的形式進行字符串的拼接
databinding中使用邏輯與運算符&&
'&' --> '&'
'<' --> '<'
'>' --> '>'
android:visibility="@{data.isOwner()==true && data.isDefault()==false ? View.VISIBLE:View.GONE}"