Android 界面库 (一) 之 View binding 简单使用

1. 简介

    在过去Android开发中,一般会使用 findViewById() 方法来获取 XML 布局文件中的 View 对象,然后对该对象进行设置文本、设置是否可见、设置点击事件回调等的视图操作。但是这种对 View 的对象获取和操作的方式会可能存在一些问题,例如:当 findViewById()  方法传入的是一个不存在的 View ID 时, 在使用该对象时就有可能会导致空指针异常;又例如因为 findViewById() 方法是一个泛型方法,若传入的类型与布局文件中的 View 类型不一致时可能会导致类型异常。而且这些异常是可能在运行时发生,这样就会影响应用程序的稳定性。

    View binding 是 Android Jetpack 库的一部分,是 Android 开发中另一种可以代替使用findViewById() 方法的技术,它旨在简化 View 与代码之间的绑定过程。它会在编译时期为每个 XML 布局文件生成相应的绑定类(Binding class),该类里包含了布局文件每个有 ID 的 View 的引用,从而避免了频繁去手动调用 findViewById() 方法获取 View 对象。这样一来,开发者就可以直接通过该 Binding class 访问布局文件中的 View,而无需担心空指针或类型转换异常的发生。

2. 启用 View binding

        如果需要在工程项目中启用 View binding,需要先在项目模块级 buid.gradle 文件中将 viewBinding 构建选项设置为 true, 如:

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

        因为 View Binding 开启后,会在编译时期为每个 XML 布局文件生成相应的 Binding class,这样也会存在一定的编译时间增加和包大小增加,若你明确某个布局文件不需要生在 Binding class,可以将 tools:viewBindingIgnore="true" 属性添加到该布局文件的根视图中,如:

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

3. 使用

    当你工程 Gradle 中配置启用 View binding 后,在工程编译阶段就会为每个布局文件生成对应的绑定类,其中类的名称规则是:XML 文件的名称转换为 Pascal 命名规则的大小写形式,并在末尾添加“Binding”。例如有一个名为 result_profile.xml 的布局文件,其中包含以下内容:

<LinearLayout ... >
    <TextView android:id="@+id/my_name" />
    <ImageView android:cropToPadding="true" />
    <Button android:id="@+id/my_button"
        android:background="@drawable/rounded_button" />
</LinearLayout>

        所生成的绑定类的名称就是 ResultProfileBinding。此类有两个字段:一个是名为 myName  的  TextView,另一个是名为 myButton 的 Button。因为布局中的 ImageView 没有 ID,所以类中没有对其的引用。

        另外每个绑定类还包含一个 getRoot() 的方法,用于提供相应布局文件的根视图的直接引用。在此示例中,ResultProfileBinding 类中的 getRoot() 方法会返回 LinearLayout 根视图。

3.1. 在 Activity 中使用 View binding

    在 Activity 的 onCreate 方法中,可以执行以下代码来绑定 Activity 和布局文件,以及获取布局文件中的 View 对象:

private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)

    binding.myName.text = “Hello world!”
    binding.myButton.setOnClickListener {
       // TODO…
    }
}

说明:

  1. 绑定类中的静态 inflate() 方法用于创建该绑定类的实例以供 Activity 使用。
  2. 通过调用 getRoot() 方法获取对根视图的引用。
  3. 将根视图传递给 setContentView(),使其成为屏幕上的Activity 的View。

3.2. 在 Fragment 中使用View binding

        若要在 Fragment 中使用绑定类,可在其 onCreateView 方法中执行以下代码:

private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(inflater: LayoutInflater,  container: ViewGroup?,  savedInstanceState: Bundle?): View? {
    _binding = ResultProfileBinding.inflate(inflater, container, false)
    val view = binding.root
    return view
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

说明:

  1. 跟 Activity 一样,使用了绑定类的静态 inflate() 方法来创建绑定类的实例,不同的是此处方法是三个参数的重载版本。
  2. 也是通过调用 getRoot() 方法获取对根视图的引用。
  3. onCreateView() 方法返回根视图对象,使其成为屏幕上的Activity 的 View。
  4. 注意在 onDestroyView 方法中记得要将绑定类置空。

3.3. 不同配置布局类型处理

        如果你的工程中存在多种配置声明View时,有时可能会存在根据特定布局使用不同类型的View 的场景,例如:

# in res/layout/example.xml

<TextView android:id="@+id/user_bio" />

# in res/layout-land/example.xml

<EditText android:id="@+id/user_bio" />

        在此情况下,你可能希望生成的 userBio 字段是 TextView 类型,因为TextView 也是 EditText 的父类,但是因为View binding 在生成代码时是无法在特殊多种配置情况下去验证布局 View 的类型,所以这里就只能默认生成了View 类型的 userBio 字段。然而在后面代码中使用该字段时就需要使用binding.userBio as TextView 来对字段进行转换。

        针对这种特殊情况,View binding 支持 tools:viewBindingType 属性,可告知编译器在生成的代码中使用什么类型。在前面的示例中,可以使用此属性让编译器将字段生成为 TextView,例如:

# in res/layout/example.xml

<TextView android:id="@+id/user_bio" />

# in res/layout-land/example.xml 

<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />

注意:

        虽然通过 tools:viewBindingType 属性可在 View binding 在生成代码时指定字段类型,但是其内部是不存在类型校验逻辑的。为避免编译时和运行时错误,该值必须满足以下条件:

  1. 该值必须是继承自 android.view.View 的类。
  2. 该值必须是放置它的代码的父类。若上述示例中将 EditText 中的 tools:viewBindingType 设为 Button 是会产生错误的。
  3. 最终类型必须在所有配置中一致地解析。

4. 总结

        从 Android 官方开发者文档 中可见,View Binding 是官方推荐的视图绑定方案。它提供了一种更安全、更高效的视图绑定方式,可以减少开发者的工作量,并提高代码的可维护性和性能,也降低了潜在的运行时错误风险。因此,如果你正在开发新的 Android 项目, View binding 是一个很不错的选择。更多详细的 View binding 介绍可前往 Android 开发者官网:https://developer.android.com/topic/libraries/view-binding?hl=zh-cn

  • 27
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然可以!以下是一个使用Kotlin在Android Studio中编写的简单登录界面的示例: 首先,在res/layout目录下创建一个名为activity_login.xml的布局文件,用于定义登录界面的UI元素。可以像这样编写: ```xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <EditText android:id="@+id/editTextUsername" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Username" android:inputType="text" /> <EditText android:id="@+id/editTextPassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Password" android:inputType="textPassword" /> <Button android:id="@+id/buttonLogin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Login" /> </LinearLayout> ``` 然后,在MainActivity.kt文件中,设置布局并处理登录逻辑。可以像这样编写: ```kotlin import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_login.* class LoginActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) buttonLogin.setOnClickListener { val username = editTextUsername.text.toString() val password = editTextPassword.text.toString() if (isValidCredentials(username, password)) { // 登录成功 // 在这里添加你的登录逻辑 } else { // 登录失败 // 在这里处理登录失败逻辑 } } } private fun isValidCredentials(username: String, password: String): Boolean { // 在这里添加验证逻辑,例如检查用户名和密码是否匹配 return username == "admin" && password == "password" } } ``` 这里使用了`kotlinx.android.synthetic`插件来简化对UI元素的访问。请确保在build.gradle文件中启用了插件依赖,例如: ```groovy android { // ... // 添加以下配置 viewBinding { enabled = true } } ``` 这是一个简单的登录界面示例,你可以根据自己的需求进行修改和扩展。希望能帮到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值