Kotlin中自定义控件TitleLayout的视图绑定优化方法

使用 GPT-4o 回答,作者 GPT4oMini.app

问题:

用Kotlin开发Android应用,自定义控件TitleLayout.kt如下: package com.example.activitytest import android.app.Activity import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.widget.Button import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout //import kotlinx.android.synthetic.main.title.view.*

class TitleLayout(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs) {

init {
    // 先膨胀布局
    LayoutInflater.from(context).inflate(R.layout.title_layout, this, true)
    val titleBack: Button = findViewById(R.id.titleBack)
    val titleEdit: Button = findViewById(R.id.titleEdit)

    titleBack.setOnClickListener {
        val activity = context as Activity
        activity.finish()
    }
    titleEdit.setOnClickListener {
        Toast.makeText(context, "You clicked Edit button", Toast.LENGTH_SHORT).show()
    }
}

}

title_layout.xml如下:

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content">

<Button
    android:id="@+id/titleBack"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Back"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />

<TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="Title Text"
    android:textColor="#fff"
    android:textSize="24sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@+id/titleEdit"
    app:layout_constraintStart_toEndOf="@+id/titleBack"
    app:layout_constraintTop_toTopOf="parent" />

<Button
    android:id="@+id/titleEdit"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Edit"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

先需要优化代码,将findViewById的方法用自动绑定的方进行改造,是否可以采用import kotlinx.android.synthetic.main.title.view.*的方式进行改造? 这个方式是否是当前主流的做法?有无更好的方式?

答案:

在Kotlin中,使用kotlinx.android.synthetic进行视图绑定曾经是一个非常流行的方式,因为它简化了视图绑定的代码。然而,Google已经宣布kotlinx.android.synthetic在未来的版本中将被弃用,因此不建议在新的项目中使用它。

目前,推荐使用的是View Binding或Data Binding。View Binding是一种更轻量级的方式,它可以生成类型安全的绑定类,避免了findViewById的繁琐和潜在的类型转换错误。

下面是如何使用View Binding来改造你的代码:

  1. 启用View Binding:在你的build.gradle文件中启用View Binding。
android {
    ...
    viewBinding {
        enabled = true
    }
}
  1. 修改TitleLayout.kt:使用View Binding来替代findViewById
package com.example.activitytest

import android.app.Activity
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import com.example.activitytest.databinding.TitleLayoutBinding

class TitleLayout(context: Context, attrs: AttributeSet) : ConstraintLayout(context, attrs) {

    private val binding: TitleLayoutBinding = TitleLayoutBinding.inflate(LayoutInflater.from(context), this, true)

    init {
        binding.titleBack.setOnClickListener {
            val activity = context as Activity
            activity.finish()
        }
        binding.titleEdit.setOnClickListener {
            Toast.makeText(context, "You clicked Edit button", Toast.LENGTH_SHORT).show()
        }
    }
}
  1. 修改title_layout.xml:不需要修改你的XML布局文件。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <Button
        android:id="@+id/titleBack"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Back"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

    <TextView
        android:id="@+id/titleText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Title Text"
        android:textColor="#fff"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/titleEdit"
        app:layout_constraintStart_toEndOf="@+id/titleBack"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/titleEdit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Edit"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

通过使用View Binding,你可以获得以下好处:

  • 类型安全:避免了类型转换错误。
  • 编译时检查:在编译时就能发现视图绑定的问题。
  • 更少的模板代码:不需要手动编