Android Studio:视图绑定的岁月变迁(2/100)

一、博文导读

本文是基于Android Studio真实项目,通过解析源码了解真实应用场景,写文的视角和读者是同步的,想到看到写到,没有上帝视角。

前期回顾,本文是第二期。

private Unbinder mUnbinder; 只是声明了一个 接口类型 的变量,并没有直接实例化。

二、Unbinder接口

这个 Unbinder 接口通常出现在基于依赖注入框架的 Android 开发中,例如 ButterKnife ,用于解绑视图引用 。它的主要作用是管理绑定的生命周期,特别是在 ActivityFragment 销毁时释放资源,防止内存泄漏。

上面的方法标记为 @UiThread,表示它只能在主线程中调用。如果尝试在后台线程调用此方法,则会导致问题。如果你在后台线程调用了这个方法(而没有切换到主线程),Android Studio 可能会发出警告。

unbind 方法

  • 这是一个抽象方法,表示解绑的操作。在 Android 开发中,绑定视图(如使用 ButterKnife.bind())后,需要在 ActivityFragment 销毁时调用 unbind 方法,释放视图资源,避免内存泄漏。

EMPTY 对象

  • Unbinder.EMPTY 是一个静态的空实现对象,作为默认实现,用于防止空指针异常。
  • 如果某个绑定没有需要解绑的资源,可以直接返回这个空实现。这样即使调用了 unbind,也不会引发异常。
java 复制代码
Unbinder unbinder = Unbinder.EMPTY; // 初始值为 EMPTY

简单的使用场景:

java 复制代码
public class MainActivity extends AppCompatActivity {
    @BindView(R.id.textView)
    TextView textView;

    private Unbinder unbinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 绑定视图
        unbinder = ButterKnife.bind(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 解绑视图,释放资源,防止内存泄漏
        unbinder.unbind();
    }
}

在活动页面销毁的时候调用解绑视图,来释放资源。

三、绑定和解绑

先看两种视图绑定的方法对比:

现代官方版本view binding举例:

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">
    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello, View Binding!"
        android:textSize="18sp" />
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />
</LinearLayout>

简单的线性布局,一个文本和一个按钮,其id分别为textView1和button1。下面是活动页面的代码:

java 复制代码
public class MainActivity extends AppCompatActivity {

    // 声明一个视图绑定对象
    //ActivityMainBinding 是根据你的 XML 文件 activity_main.xml 自动生成的绑定类。
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        //ActivityMainBinding.inflate() 方法会加载 activity_main.xml 布局文件。
        //getLayoutInflater() 是 Android 提供的工具,用于将 XML 文件转化为对应的视图对象。
        //结果:binding 变量现在就代表了整个布局,里面包含了所有控件的直接引用。
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // 使用绑定对象直接访问视图
        binding.textView1.setText("Welcome to View Binding!");
        binding.button1.setOnClickListener(v ->
                Toast.makeText(this, "Button clicked!", Toast.LENGTH_SHORT).show()
        );
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 防止内存泄漏
        binding = null;
    }
}

工作原理:

  • 直接生成绑定类 :视图绑定会为每个布局文件自动生成一个对应的绑定类,比如 activity_main.xml 会生成 ActivityMainBinding
  • 通过绑定类访问控件 :直接通过 binding 对象访问控件,无需手动查找视图。
  • 视图绑定的优势是直接通过 binding 对象访问控件,类型安全且简洁高效,不再需要 findViewById

以下是使用 ButterKnife 所需的完整配置,包括依赖、代码示例以及运行步骤:

1. 添加 ButterKnife 的依赖

在你的 build.gradle 文件中,添加以下依赖:

项目根目录的 build.gradle

确保添加 ButterKnife 的 Maven 仓库:

java 复制代码
allprojects {
    repositories {
        google()
        mavenCentral()
    }
}
模块的 build.gradle

dependencies 中添加 ButterKnife 的依赖:

java 复制代码
dependencies {
    // 添加 ButterKnife 的核心库
    implementation 'com.jakewharton:butterknife:10.2.3'
    // 添加 ButterKnife 的注解处理器(用于生成代码)
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
}

xml界面不变,创建 MainActivity.java 并添加以下代码:

java 复制代码
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MainActivity extends AppCompatActivity {

    // 使用 @BindView 注解绑定布局中的控件
    @BindView(R.id.textView) TextView textView;
    @BindView(R.id.button) Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化 ButterKnife
        ButterKnife.bind(this);

        // 设置默认文本
        textView.setText("Welcome to ButterKnife!");
    }

    // 使用 @OnClick 注解绑定点击事件
    @OnClick(R.id.button)
    void onButtonClick() {
        Toast.makeText(this, "Button clicked!", Toast.LENGTH_SHORT).show();
    }
}

老版本的试图绑定,还是很麻烦的。

相关推荐
此去正年少11 分钟前
编写adb脚本工具对Android设备上的闪退问题进行监控分析
android·adb·logcat·ndk·日志监控
落羽凉笙31 分钟前
Python基础(4)| 玩转循环结构:for、while与嵌套循环全解析(附源码)
android·开发语言·python
十幺卜入1 小时前
Unity3d C# 基于安卓真机调试日志抓取拓展包(Android Logcat)
android·c#·unity 安卓调试·unity 安卓模拟·unity排查问题
frontend_frank1 小时前
脱离 Electron autoUpdater:uni-app跨端更新:Windows+Android统一实现方案
android·前端·javascript·electron·uni-app
薛晓刚2 小时前
MySQL的replace使用分析
android·adb
DengDongQi2 小时前
Jetpack Compose 滚轮选择器
android
stevenzqzq2 小时前
Android Studio Logcat 基础认知
android·ide·android studio·日志
代码不停2 小时前
MySQL事务
android·数据库·mysql
朝花不迟暮2 小时前
使用Android Studio生成apk,卡在Running Gradle task ‘assembleDebug...解决方法
android·ide·android studio
yngsqq2 小时前
使用VS(.NET MAUI)开发第一个安卓APP
android·.net