详解Android控件状态依赖框架
作者:yhthu 发布时间:2023-07-01 10:01:06
在生产型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


猜你喜欢
- CollectionCollection接口被List接口和Set接口继承本章只介绍常用的集合ListArrayList是List接口的实现
- spring xml文件打开没有namespace等操作选项第一步查看自己安装的eclipse的正确的版本号:打开eclipse,点击hel
- schedule的四种用法schedule(task,time)task-所安排的任务 time-执行任务的时间作用:在时间等于
- 1.例题题目描述迷宫由 n 行 m 列的单元格组成,每个单元格要么是空地,要么是障碍物。其中1表示空地,可以走通,2表示障碍物。给定起点坐标
- C#实现的对两个Table进行Merge,两表必须存在至少一个公共栏位作为连接项,否则连接就失去了意义。如下是对两个table进行Merge
- 接收 / 返回文本消息①接收/返回文本消息原理说明当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的UR
- 简介过滤器是AOP(面向切面编程)思想的具体实现。可以过滤浏览器发出的请求,并且决定放行请求还是中断请求。在浏览器对服务器发起请求或者服务器
- 摘要分析验证码素材图片混淆原理,并采用selenium模拟人拖动滑块过程,进而破解验证码。人工验证的过程1、打开威锋网注册页面2、移动鼠标至
- 前言一般在写业务接口的过程中,很有可能需要实现可以动态组合各种查询条件的接口。如果我们根据一种查询条件组合一个方法的做法来写,那么将会有大量
- 当你要做一个图库的项目时,对图片大小、像素的控制是首先需要解决的难题。一、单图生成略缩图单图经过重新绘制,生成新的图片。新图可以按一定比例由
- 如下所示:class Program {
- Activity中Toast的使用Toast.makeText(this,"ADD",Toast.LENGTH_SHOR
- 一个完整的http响应包括响应行,若干响应头和响应数据主体三部分构成。如果我们能用响应对象来进行这三部分的处理,就能向客户发送特定的响应数据
- 本文实例讲述了C#远程发送和接收数据流生成图片的方法。分享给大家供大家参考。具体如下:将图片转成数据流方式发送到远程服务,在通过服务器后台程
- 本地仓库是指存在于我们本机的仓库,在我们加入依赖时候,首先会跑到我们的本地仓库去找,如果找不到则会跑到远程仓库中去找。对于依赖的包大家可以从
- 简介我们在使用flutter的过程中,有时候需要控制某些组件是否展示,一种方法是将这个组件从render tree中删除,这样这个组件就相当
- Java中重载与重写的区别首先我们来讲讲:重载(Overloading) (1) 方法重载是让类以统一的
- 逆转交替合并两个链表,即从一个链表的尾指针指向另一个链表的尾指针,依次逆转交替进行合并。下面就通过实例来详细的介绍该逆转交替合并两个链表的思
- 本文将基于Spring Boot介绍两种生成二维码的实现方式,一种是基于Google开发工具包,另一种是基于Hutool来实现;
- public void PrintPercentage(int FinishedCount, int TotalCount) {