目录
一、简单绑定
1.配置gradle
2.更改布局文件
3.实例化布局文件
4.传递数据到布局文件
二、响应事件
1.新建事件响应类
2.布局添加
3.绑定数据
4.绑定响应方法
三、二级页面绑定
1.适用场景
2.绑定方法
(1)一级界面传递数据
(2)二级界面接收数据
四、自定义BindingAdapter
1.用途
2.使用
(1)配置gradle
(2)自定义BindingAdapter
(3)调用BindingAdapter
五、双向绑定
1.用途
2.使用
(1)新建Model类
(2)新建ViewModel类
六、双向绑定结合LiveData
1.用LiveData包装数据类
2.改造ViewModel
3.activity中观察LiveData
七、RecyclerView绑定
1.创建item布局
2.创建Adapter
3.activity中加载数据
打开module层级的build.gradle文件,在android层级下添加如下代码
dataBinding{
enabled = true
}
在布局文件中,光标移至最前面,按Alt+Enter,选择Convert to data binding layout,studio将自动更改为databinding布局
val binding: ActivityDataBindingBinding =
DataBindingUtil.setContentView(this, R.layout.activity_data_binding)
布局文件中节点下添加
activity中传递数据
binding.book = Book("title", "author", 5)
在布局文件中绑定数据
布局文件中引用静态类,在节点添加引用
使用进入到静态类
注:实际测试过程中,Kotlin的伴生对象静态方法在布局文件中引用会报错,后续将继续排查报错原因,故此处
(原因已查明,参考https://blog.csdn.net/jie1123161402/article/details/81736677)
运行效果:
在activity中新建内部类,或独立成单独类文件
class EventHandleListener(var context:Context) {
fun onClick(view: View) {
Toast.makeText(context, "Clicked!", Toast.LENGTH_SHORT).show()
}
}
在activity中绑定数据
binding.eventHandler=EventHandleListener(this)
在onclick中绑定响应方法
运行效果
使用于在布局文件中使用
布局变量book同时也是命名空间xmlns:app的一个属性,通过app:book传递数据
新建layout_content.xml,使用variable接收绑定数据,在TextView中使用绑定数据
为了让布局文件能承担更多的工作,处理更复杂的业务逻辑。
为了加载图片,引入Glide依赖
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
class ImageViewBindingAdapter {
companion object{
@BindingAdapter("image")
@JvmStatic
fun setImage(imageView: ImageView, imageUrl: String) {
if (imageUrl.isNotEmpty()) {
Glide.with(imageView)
.load(imageUrl)
.placeholder(R.mipmap.ic_launcher)
.error(R.mipmap.ic_launcher)
.into(imageView)
} else {
imageView.setBackgroundColor(Color.GRAY)
}
}
}
}
布局文件添加如下代码:
activity添加如下代码:
binding.networkImage="https://avatar.csdnimg.cn/0/F/2/1_u010444082.jpg"
运行效果:
简单绑定只能实现将数据绑定到视图上,双向绑定可以通过视图中控件的交互来直接改变数据,减少了在activity或viewModel中来对数据进行操作
双向绑定与简单绑定类似,只不过在布局文件中,绑定的数据由原来的"@{}"变为"@={}",并在ViewModel中编写对应数据的get/set方法
class LoginModel(var userName:String)
viewModel中需要用ObservableField类来包装数据类,并且编写数据的set/get方法才能实现双向绑定
open class TwoWayBindingViewModel {
private val loginModel = LoginModel("Keep Coding!")
val observableField = ObservableField()
init {
observableField.set(loginModel)
}
fun setUserName(userName: String) {
observableField.get()!!.userName = userName
}
fun getUserName(): String {
return observableField.get()!!.userName
}
(3)在布局文件中进行双向绑定
(4)activity中传入viewModel
binding = DataBindingUtil.setContentView(this, R.layout.activity_two_way_binding)
viewModel = TwoWayBindingViewModel()
binding.viewModel = viewModel
fun getUserName(view: View) {
binding.tv.text=viewModel.observableField.get()!!.userName
}
运行效果:
进入页面,EditText中显示userName的初始值“KeepCoding!”更改EditText中的值,点击按钮,发现viewModel中LoginModel数据类中的userName已被更改 ,并显示到下方TextView中
上一节中userName值的改变需要通过按钮重新获取才能显示更新,本节将改造上节代码,实现EditText中的值改变,TextView同步显示改变后的值
class LoginModel(var userName:MutableLiveData)
open class TwoWayBindingViewModel {
private val loginModel = LoginModel(MutableLiveData("Keep Coding!"))
val observableField = ObservableField()
init {
observableField.set(loginModel)
}
fun setUserName(userName: String) {
observableField.get()!!.userName.value = userName
}
fun getUserName(): String? {
return observableField.get()!!.userName.value
}
}
viewModel.observableField.get()!!.userName.observe(this){
binding.tv.text=it
}
运行效果:
此时改变EditText中的内容,TextView中的内容也同步改变
class BookAdapter(var books: List) : RecyclerView.Adapter() {
lateinit var binding: ItemBookBinding
class BookViewHolder(binding: ItemBookBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookViewHolder {
binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
R.layout.item_book,
parent,
false
)
return BookViewHolder(binding)
}
override fun onBindViewHolder(holder: BookViewHolder, position: Int) {
binding.book = books[position]
}
override fun getItemCount(): Int {
return books.size
}
}
binding = DataBindingUtil.setContentView(this, R.layout.activity_recycler_view_binding)
val list = ArrayList()
for (i in 0..100) {
val book = Book("Jetpack", "Keep Coding!", i % 6)
book.imageUrl = "https://avatar.csdnimg.cn/0/F/2/1_u010444082.jpg"
list.add(book)
}
binding.rv.layoutManager = LinearLayoutManager(this)
binding.rv.adapter = BookAdapter(list)
运行效果:
源码已上传Gtihub
https://github.com/ZYALLZ/AndroidJetpack