详解Android控件状态依赖框架

发布时间 - 2026-01-11 00:22:08    点击率:

在生产型Android客户端软件(企业级应用)开发中,界面可能存在多个输入(EditText)和多个操作(MotionEvent和KeyEvent),且操作依赖于输入的状态。如下图所示的场景:

设定图中

  • 确认操作依赖于商品编码和储位的状态
  • 跳过操作不依赖于输入状态
  • 登记差异操作依赖于储位和数量的状态

输入框有三种状态:

  • 待输入;
  • 待校验;
  • 校验成功。

操作需要当其依赖的输入数据校验成功,才能执行。

如果在Activity中去判断输入框状态,那么实际需要调用(3个输入框)*(3种状态)*(3个按钮) = 27个 if 判断,对于状态的维护将使得整个程序可维护性极差,并随着输入和操作的增加,维护的状态呈指数增长。

通过对这种场景的抽象,实现了Android控件状态依赖框架,其使用方法如下:

使用方法:

1、布局文件引用WatchEditText和WatchButton

<com.android.yhthu.viewdependency.view.WatchEditText
android:id="@+id/edit_query_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:tag="editQuery1"
android:imeOptions="actionNext"
android:hint="商品编码"
android:inputType="number"/>
<com.android.yhthu.viewdependency.view.WatchButton
android:id="@+id/search_button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tag="buttonSearch1"
android:text="确认" />

由于Library Module中的控件id不是常量(可参考ButterKnife对Library Module的支持采用R2的原因),这里采用了tag的方式。

2、在Activity中通过注解申明依赖

@ViewName("商品编码")
private WatchEditText editQuery1;
@ViewName("储位")
private WatchEditText editQuery2;
@ViewName("数量")
private WatchEditText editQuery3;
@ViewDependency(name = @ViewName("确认"), dependency = {"editQuery1", "editQuery2"})
private WatchButton buttonSearch1;
@ViewDependency(name = @ViewName("跳过")/*不依赖输入*/)
private WatchButton buttonSearch2;
@ViewDependency(name = @ViewName("登记缺货"), dependency = {"editQuery2", "editQuery3"})
private WatchButton buttonSearch3;

ViewName定义控件名称,ViewDependency中dependency指定其依赖的控件tag。

3、直接执行onClick和onEditorAction(修改状态)

@Override
public void onClick(View v) {
if (v == buttonSearch1) {
 Toast.makeText(this, "调接口", Toast.LENGTH_SHORT).show();
} else if (v == buttonSearch2) {
 Toast.makeText(this, "跳下一页", Toast.LENGTH_SHORT).show();
} else if (v == buttonSearch3) {
 Toast.makeText(this, "登记缺货", Toast.LENGTH_SHORT).show();
}
}

可以看出,这里并没有通过if判断各个输入控件的状态。

@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_NEXT && v == editQuery1
 && (query1Str = editQuery1.getText().toString()).isEmpty()) {
 if (query1Str.equals("12345")) {
 editQuery1.complete();
 return true;
 }
} 
// 省略代码
return false;
}

onEditorAction模拟调用软件的Enter进行校验,这里需要注意通过editQuery1.complete()修改该EidtText的状态。

实现原理

整个框架分为三个package:annotation、state和view。

1、在annotation中定义ViewName和ViewDependency注解,分别用于WatchEditText和WatchButton。ViewName指定WatchEditText控件在业务中的名称,ViewDependency指定WatchButton依赖的WatchEditText控件;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ViewDependency {

ViewName name() default @ViewName;

String[] dependency() default {};
}

2、在state中通过状态模式定义Enter、Verify、Complete,其基类为抽象类Operator,定义方法operator;

public abstract class Operator {

// 操作对应的上下文
protected Context context;
// 操作
public abstract boolean operator(String operatorName, String viewName);
}

public class Enter extends Operator {

private static Enter enter;

private Enter(Context context) {
 this.context = context;
}

public static Enter getInstance(Context context) {
 if (enter == null) {
 enter = new Enter(context);
 }
 return enter;
}

@Override
public boolean operator(String operatorName, String viewName) {
 Toast.makeText(context, String.format("[%s]为空,不允许执行[%s]", viewName, operatorName),
  Toast.LENGTH_SHORT).show();
 return false;
}
}

3、WatchEditText和WatchButton定义控件的依赖关系。WatchEditText实现ViewState接口,其包含三种状态的转换方法。

public interface ViewState {
void enter();
void verify();
void complete();
}

以上,博客园对markdown支持的不太好,无法添加注释(/* */),如需查看源码,请移步Github地址:https://github.com/yhthu/AndroidViewDependency.git

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Android  # 控件状态  # 依赖框架  # android实现圆环倒计时控件  # Android Studio给各种控件加边框的操作方法  # Android自定义view实现倒计时控件  # Android实现简单的下拉刷新控件  # Android日期选择控件使用详解  # Android自定义控件横向柱状统计图  # Android APT 实现控件注入框架SqInject的示例  # 输入框  # 多个  # 依赖于  # 跳过  # 采用了  # 三种  # 生产型  # 可以看出  # 所示  # 中去  # 如需  # 跳下  # 需要注意  # 图中  # 有三种  # 大家多多  # 如下图  # 为空  # 方法如下  # 客户端软件 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  如何在香港免费服务器上快速搭建网站?  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  如何快速生成橙子建站落地页链接?  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  详解jQuery中基本的动画方法  Laravel怎么实现支付功能_Laravel集成支付宝微信支付  南京网站制作费用,南京远驱官方网站?  详解Android图表 MPAndroidChart折线图  如何做网站制作流程,*游戏网站怎么搭建?  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  如何续费美橙建站之星域名及服务?  Laravel如何使用Eloquent进行子查询  Python进程池调度策略_任务分发说明【指导】  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  JS实现鼠标移上去显示图片或微信二维码  Laravel如何使用模型观察者?(Observer代码示例)  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  简单实现Android文件上传  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  Thinkphp 中 distinct 的用法解析  BootStrap整体框架之基础布局组件  linux写shell需要注意的问题(必看)  今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  如何用景安虚拟主机手机版绑定域名建站?  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  java ZXing生成二维码及条码实例分享  ,南京靠谱的征婚网站?  香港服务器建站指南:免备案优势与SEO优化技巧全解析  教你用AI将一段旋律扩展成一首完整的曲子  免费网站制作appp,免费制作app哪个平台好?  phpredis提高消息队列的实时性方法(推荐)  Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】  Laravel如何实现用户密码重置功能?(完整流程代码)  高性能网站服务器配置指南:安全稳定与高效建站核心方案  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  Laravel项目结构怎么组织_大型Laravel应用的最佳目录结构实践  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  Firefox Developer Edition开发者版本入口  Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧  如何实现建站之星域名转发设置?  Laravel如何配置和使用缓存?(Redis代码示例)  WEB开发之注册页面验证码倒计时代码的实现  油猴 教程,油猴搜脚本为什么会网页无法显示?  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工