欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Jetpack DataBinding数据绑定

程序员文章站 2022-06-15 09:35:13
Jetpack DataBinding数据绑定简介DataBinding是Google提供的将视图和数据绑定的支持库,主要是为了简化代码,去除findViewById() 等样式代码的调用,借助布局文件中的绑定组件,您可以移除 Activity 中的许多界面框架调用,使其维护起来更简单、方便。还可以提高应用性能,并且有助于防止内存泄漏以及避免发生 Null 指针异常。依赖在app的build.gradle文件中添加依赖:apply plugin: 'kotlin-kapt'android {...

Jetpack DataBinding数据绑定

简介
DataBinding是Google提供的将视图和数据绑定的支持库,主要是为了简化代码,去除findViewById() 等样式代码的调用,借助布局文件中的绑定组件,您可以移除 Activity 中的许多界面框架调用,使其维护起来更简单、方便。还可以提高应用性能,并且有助于防止内存泄漏以及避免发生 Null 指针异常。

依赖
Jetpack DataBinding数据绑定
在app的build.gradle文件中添加依赖:

apply plugin: 'kotlin-kapt'
android {
    ......
    
    //开启dataBinding
    dataBinding {
        enabled = true
    }
}
dependencies {
    ......
    
    //databinding版本跟Gradle版本一致
    kapt "com.android.databinding:compiler:$gradle_version"
}

项目的build.gradle配置如下:

buildscript {
    ext.kotlin_version = '1.3.50'
    ext.gradle_version = '3.5.1'
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$gradle_version"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

Activity/Fragment中使用DataBinding
可通过在根布局上Alt+Enter(Windows下)快捷键生成绑定布局:
Jetpack DataBinding数据绑定
布局文件acitivity_main.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>
        <import 
            type="com.zzs.jetpack_databinding.User"
            alias="UserInfo"/>
        <variable
            name="user"
            type="UserInfo" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            ......
            android:text="@{user.name}" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

注意:布局文件嵌套layout后,会生成一个binding类,类名为布局文件的名称驼峰式+Binding,如:ActivityMainBinding,如果没有找到binding类,Rebuild Project一下项目就可以了

data属性详解:

  • import:引入数据类型

    type: 数据类型
    alias:类型别名,防止不同路径下的相同类名重复

  • variable:变量声明

    name:布局中使用的类名,如: android:text="@{user.name}"
    type: 设置了别名就使用别名,否则就使用类名,如:User,
    不导入数据类型(不使用import)则使用完整地址,
    如: com.zzs.jetpack_databinding.User

常用数据类型引入:

<data>
        <import type="android.util.SparseArray"/>
        <import type="java.util.Map"/>
        <import type="java.util.List"/>
        <import type="com.zzs.jetpack_databinding.User"/>
        <variable name="list" type="List&lt;String>"/>
        <variable name="sparse" type="SparseArray&lt;String>"/>
        <variable name="map" type="Map&lt;String, String>"/>
        <variable name="index" type="int"/>
        <variable name="key" type="String"/>
        <variable name="user" type="User" />
    </data>
    …
    android:text="@{list[index]}"
    …
    android:text="@{sparse[index]}"
    …
    android:text="@{map[key]}"//没有定义key,可以android:text='@{map["name"]}'
                              //           或者android:text="@{map[`name`]}"
    …
    android:text="@{user.name}"

引用资源:

android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"

注意:要使 XML 不含语法错误,您必须转义 < 字符。例如:不要写成 List< String >形式,而是必须写成
Jetpack DataBinding数据绑定

User数据类:

data class User(
    val name:String,
    val age:Int
)

在Activity中代码如下:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //绑定试图
        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
        //绑定数据类
        binding.user = User("张三",20)//User是我自己创建的数据类
    }
}

在Fragment中代码如下:

class BlankFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding = DataBindingUtil.inflate<FragmentBlankBinding>(inflater,R.layout.fragment_blank, container, false)
        return binding.root
    }
    
}

注意:第一次没有找到DataBindingUtil类,重启一下项目就好了

处理页面点击事件:
布局文件代码:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="user"
            type="com.zzs.jetpack_databinding.User" />
        <variable
            name="myHandles"
            type="com.zzs.jetpack_databinding.MainActivity.MyHandlers" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:onClick="@{(view)-> myHandles.onClickUser(view,user)}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Activity/Fragment代码:

class MainActivity : AppCompatActivity() {

     override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val binding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        binding.user = User("张三", 20)
        //不要忘记写这个,不然点击事件无效
        binding.myHandles = MyHandlers()
    }

    inner class MyHandlers{
        fun onClickUser(view: View,user: User){
            //处理点击事件逻辑
            Toast.makeText(this@MainActivity, user.name, Toast.LENGTH_SHORT).show()
        }
    }
}

RecyclerView中使用DataBinding
RecyclerView布局文件代码:

<layout  xmlns:android="http://schemas.android.com/apk/res/android">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_user"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"/>
 
</layout>

item列表布局文件代码:

<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="userList"
            type="com.zzs.jetpack_databinding.User" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{userList.name}"
            android:padding="10dp" />

    </LinearLayout>
</layout>

初始化:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val binding =
            DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        val users = ArrayList<User>().apply {
            for (i in 0..10) {
                add(User("张三$i", 20))
            }
        }
        binding.rvUser.layoutManager = LinearLayoutManager(this)
        val adapter = UserAdapter(this, users);
        binding.rvUser.adapter = adapter
        //item点击事件
        adapter.setOnItemClickListener(object : UserAdapter.OnItemClickListener {
            override fun onItemClick(view: View, user: User) {
                Toast.makeText(this@MainActivity, user.name, Toast.LENGTH_SHORT).show()
            }

        })
    }
}

UserAdapter适配器:

class UserAdapter(private val context: Context, private val users: List<User>) :
    RecyclerView.Adapter<UserAdapter.ViewHolder>() {
    private lateinit var mOnClickListener: OnItemClickListener

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            DataBindingUtil.inflate(
                LayoutInflater.from(context),
                R.layout.item_list_user,
                parent,
                false
            )
        )
    }

    override fun getItemCount(): Int {
        return users.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val binding = holder.dataBinding
        binding.setVariable(BR.userList, users[position])
        holder.itemView.setOnClickListener {
            //创建回调接口处理item点击事件
            mOnClickListener.onItemClick(it, users[position])
            //也可以不使用回调接口(注释上面的代码),直接在Adapter中处理点击逻辑
            //todo
        }
    }

    inner class ViewHolder(var dataBinding: ViewDataBinding) :
        RecyclerView.ViewHolder(dataBinding.root)

    interface OnItemClickListener {
        fun onItemClick(view: View, user: User)
    }

    fun setOnItemClickListener(onClickListener: OnItemClickListener) {
        this.mOnClickListener = onClickListener
    }

}

显示:
Jetpack DataBinding数据绑定

本文地址:https://blog.csdn.net/summerrse/article/details/107414378