Android Studio:视图绑定的岁月变迁(2/100)
一、博文导读
本文是基于Android Studio真实项目,通过解析源码了解真实应用场景,写文的视角和读者是同步的,想到看到写到,没有上帝视角。
前期回顾,本文是第二期。
private Unbinder mUnbinder;
只是声明了一个 接口类型 的变量,并没有直接实例化。
二、Unbinder接口
这个 Unbinder
接口通常出现在基于依赖注入框架的 Android 开发中,例如 ButterKnife,用于解绑视图引用。它的主要作用是管理绑定的生命周期,特别是在 Activity
或 Fragment
销毁时释放资源,防止内存泄漏。
上面的方法标记为 @UiThread
,表示它只能在主线程中调用。如果尝试在后台线程调用此方法,则会导致问题。如果你在后台线程调用了这个方法(而没有切换到主线程),Android Studio 可能会发出警告。
unbind
方法:
- 这是一个抽象方法,表示解绑的操作。在 Android 开发中,绑定视图(如使用
ButterKnife.bind()
)后,需要在Activity
或Fragment
销毁时调用unbind
方法,释放视图资源,避免内存泄漏。
EMPTY
对象:
Unbinder.EMPTY
是一个静态的空实现对象,作为默认实现,用于防止空指针异常。- 如果某个绑定没有需要解绑的资源,可以直接返回这个空实现。这样即使调用了
unbind
,也不会引发异常。
Unbinder unbinder = Unbinder.EMPTY; // 初始值为 EMPTY
简单的使用场景:
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 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。下面是活动页面的代码:
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 仓库:
allprojects {
repositories {
google()
mavenCentral()
}
}
模块的 build.gradle
在 dependencies
中添加 ButterKnife 的依赖:
dependencies {
// 添加 ButterKnife 的核心库
implementation 'com.jakewharton:butterknife:10.2.3'
// 添加 ButterKnife 的注解处理器(用于生成代码)
annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
}
xml界面不变,创建 MainActivity.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();
}
}
老版本的试图绑定,还是很麻烦的。