Android开发学习笔记——8、控件button(codex补充)
codex补充:
把笔记给codex审核后,补充笔记如下。
## View Binding
### 1. 作用
View Binding 会根据 XML 布局生成 Binding 类,用于替代 `findViewById()`。
例如:
```text
activity_main.xml → ActivityMainBinding
btn_submit → binding.btnSubmit
优点:
- 减少重复代码
- 提供类型安全
- 降低控件 ID 写错导致的空指针风险
2. 启用
在模块级 build.gradle 中配置:
android {
buildFeatures {
viewBinding true
}
}
3. Activity 中使用
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.btnSubmit.setOnClickListener(v ->
binding.tvResult.setText("提交成功")
);
}
}
使用 View Binding 后,应通过:
setContentView(binding.getRoot());
加载布局,不再使用:
setContentView(R.layout.activity_main);
4. Fragment 中使用
public class HomeFragment extends Fragment {
private FragmentHomeBinding binding;
@Override
public View onCreateView(
LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentHomeBinding.inflate(inflater, container, false);
return binding.getRoot();
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}
Fragment 的 View 销毁后必须清空 Binding,避免继续持有旧 View。
防止按钮重复点击
重复点击可能导致:
- 重复发送请求
- 重复提交订单
- 重复页面跳转
- 重复弹出对话框
1. 短时间点击防抖
适合页面跳转、弹窗等本地操作。
private long lastClickTime = 0L;
private static final long CLICK_INTERVAL = 800L;
private boolean isFastClick() {
long currentTime = SystemClock.elapsedRealtime();
if (currentTime - lastClickTime < CLICK_INTERVAL) {
return true;
}
lastClickTime = currentTime;
return false;
}
使用:
binding.btnNext.setOnClickListener(v -> {
if (isFastClick()) {
return;
}
openNextPage();
});
建议使用 SystemClock.elapsedRealtime(),因为它不会受到系统时间修改的影响。
2. 异步操作期间禁用按钮
适合登录、提交订单、上传文件等网络操作。
private boolean isSubmitting = false;
private void submit() {
if (isSubmitting) {
return;
}
isSubmitting = true;
binding.btnSubmit.setEnabled(false);
binding.btnSubmit.setText("提交中");
requestData();
}
请求结束后恢复:
private void finishSubmit() {
isSubmitting = false;
binding.btnSubmit.setEnabled(true);
binding.btnSubmit.setText("提交");
}
成功和失败时都要调用 finishSubmit(),否则按钮可能一直处于禁用状态。
3. 使用原则
| 场景 | 推荐方式 |
|---|---|
| 页面跳转、弹窗 | 时间防抖 |
| 登录、提交、上传 | 业务状态 + 禁用按钮 |
| 支付、订单等关键业务 | 客户端防重复 + 服务端幂等 |
客户端只能减少误操作。支付、订单等重要业务还必须由服务端根据唯一请求标识防止重复执行。
```
监听器写法与选择
1. 推荐:独立 Lambda
每个按钮分别绑定自己的点击逻辑:
binding.btnLogin.setOnClickListener(v -> login());
binding.btnRegister.setOnClickListener(v -> register());
适合:
- 按钮执行不同功能
- 点击逻辑较短
- 大多数普通页面
优点:
- 代码简洁
- 控件与行为对应清晰
- 不需要根据 ID 再次判断来源
逻辑较多时,应提取为独立方法:
binding.btnSubmit.setOnClickListener(v -> submitForm());
private void submitForm() {
// 表单校验
// 提交数据
}
不要把大量业务代码直接写进 Lambda。
2. 相关按钮:共享监听器
多个按钮属于同一组操作时,可以共享监听器:
View.OnClickListener listener = v -> {
int id = v.getId();
if (id == R.id.btn_one) {
handleButtonOne();
} else if (id == R.id.btn_two) {
handleButtonTwo();
}
};
binding.btnOne.setOnClickListener(listener);
binding.btnTwo.setOnClickListener(listener);
适合:
- 数字键盘按钮
- 筛选或排序按钮
- 播放、暂停等同类操作
- 多个按钮执行相似逻辑
如果逻辑只存在少量差异,可以直接传递参数,避免 ID 判断:
binding.btnOne.setOnClickListener(v -> selectType(1));
binding.btnTwo.setOnClickListener(v -> selectType(2));
这种写法通常比共享监听器更直观。
建议使用
if/else判断资源 ID。现代 Android Gradle Plugin 中,资源 ID 不一定是编译期常量,switch (v.getId())在部分项目中可能无法编译。
3. 匿名内部类
Java 8 以前常使用匿名内部类:
binding.btnSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
submitForm();
}
});
它与 Lambda 功能相同,但代码更长。
现在通常优先使用:
binding.btnSubmit.setOnClickListener(v -> submitForm());
匿名内部类适合学习接口回调原理,或需要创建无法使用 Lambda 的复杂接口实现。
4. Activity 实现监听接口
传统写法是让 Activity 实现 View.OnClickListener:
public class MainActivity extends AppCompatActivity
implements View.OnClickListener {
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_login) {
login();
}
}
}
绑定时统一传入 this:
binding.btnLogin.setOnClickListener(this);
这种方式不是“按钮越多越适合”。按钮较多时,所有判断集中在一个 onClick() 中,容易造成:
- 条件判断过多
- 方法体过长
- 控件和行为距离较远
- 后期维护困难
现代项目一般优先使用独立 Lambda,只有多个控件确实需要共享处理流程时才集中处理。
5. 静态内部监听器
static class SubmitClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
// 点击逻辑
}
}
这种写法适合监听器需要复用、单独测试或封装时使用。
普通页面点击事件不建议专门创建静态内部类,因为会增加类和参数传递,降低代码可读性。
6. 选择原则
| 场景 | 推荐写法 |
|---|---|
| 按钮功能互不相同 | 独立 Lambda |
| 逻辑较长 | Lambda 调用独立方法 |
| 多个按钮只有参数不同 | Lambda 传递参数 |
| 多个按钮共享处理流程 | 共享监听器 |
| 需要复用或单独测试 | 独立监听器类 |
| 学习接口回调原理 | 匿名内部类或 Activity 实现接口 |
核心原则:
是否共享监听器取决于按钮行为是否相关,而不是按钮数量。默认优先使用独立 Lambda,并将复杂业务提取为方法。
更多推荐





所有评论(0)