详解Android控件状态依赖框架

在生产型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

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

时间: 2024-09-21 09:16:02

详解Android控件状态依赖框架的相关文章

详解Android首选项框架的使用实例_Android

首选项这个名词对于熟悉Android的朋友们一定不会感到陌生,它经常用来设置软件的运行参数. Android提供了一种健壮并且灵活的框架来处理首选项.它提供了简单的API来隐藏首选项的读取和持久化,并且提供了一个优雅的首选项界面. 首先,我们来看下面这款软件的首选项界面: 这款软件使用了好几种类型的首选项,每一种首选项都有其独特的用法,下面我们来了解一下几种常见的首选项: CheckBoxPreference:用来打开或关闭某个功能 ListPreference:用来从多个选项中选择一个值: E

详解Android的MVVM框架 - 数据绑定

本教程是跟着 Data Binding Guide 学习过程中得出的一些实践经验,同时修改了官方教程的一些错误,每一个知识点都有对应的源码,争取做到实践与理论相结合. Data Binding 解决了 Android UI 编程中的一个痛点,官方原生支持 MVVM 模型可以让我们在不改变既有代码框架的前提下,非常容易地使用这些新特性.其实在此之前,已经有些第三方的框架可以支持 MVVM 模型,无耐由于框架的侵入性太强,导致一直没有流行起来. 准备 Android Studio 更新到 1.3

详解Android首选项框架的使用实例

首选项这个名词对于熟悉Android的朋友们一定不会感到陌生,它经常用来设置软件的运行参数. Android提供了一种健壮并且灵活的框架来处理首选项.它提供了简单的API来隐藏首选项的读取和持久化,并且提供了一个优雅的首选项界面. 首先,我们来看下面这款软件的首选项界面: 这款软件使用了好几种类型的首选项,每一种首选项都有其独特的用法,下面我们来了解一下几种常见的首选项: CheckBoxPreference:用来打开或关闭某个功能 ListPreference:用来从多个选项中选择一个值: E

详解Android主流框架不可或缺的基石

探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Android多分辨率适配框架(3)- 使用指南 自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View

详解Android中Intent对象与Intent Filter过滤匹配过程_Android

如果对Intent不是特别了解,可以参见博文<详解Android中Intent的使用方法>,该文对本文要使用的action.category以及data都进行了详细介绍.如果想了解在开发中常见Intent的使用,可以参见<Android中Intent习惯用法>. 本文内容有点长,希望大家可以耐心读完. 本文在描述组件在manifest中注册的Intent Filter过滤器时,统一用intent-filter表示. 一.概述 我们知道,Intent是分两种的:显式Intent和隐式

详解Android中Handler的内部实现原理_Android

本文主要是对Handler和消息循环的实现原理进行源码分析,如果不熟悉Handler可以参见博文<详解Android中Handler的使用方法>,里面对Android为何以引入Handler机制以及如何使用Handler做了讲解. 概括来说,Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制.我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功

详解Java的Struts框架中上传文件和客户端验证的实现_java

文件上传 Struts 2框架提供了内置支持处理文件上传使用基于HTML表单的文件上传.上传一个文件时,它通常会被存储在一个临时目录中,他们应该由Action类进行处理或移动到一个永久的目录,以确保数据不丢失. 请注意,服务器有一个安全策略可能会禁止写到目录以外的临时目录和属于web应用的目录. 在Struts中的文件上传是通过预先定义的拦截文件上传拦截器这是可通过org.apache.struts2.interceptor.FileUploadInterceptor类的defaultStack

基于 SurfaceView 详解 android 幸运大转盘,附带实例app

基于 SurfaceView 详解 android 幸运大转盘,附带实例app       首先说一下,幸运大转盘,以及SurfaceView是在看了也为大神的博客,才有了比较深刻的理解,当然这里附上这位大神的博客地址:博客地址,有兴趣的话你可以去看看,里面有很多的例子.至于我为什么要写这篇博客?,原因之一:加强自己的理解,原因之二:大神的博客就是大神的博客,跳转的太快,基础不好的,很难理解.还有就是一天在实验室太无聊了,没事写写东西.这里我再来更加基础的分析一下.写的不好,原谅.有什么写的不对

详解JavaScript的AngularJS框架中的作用域与数据绑定_AngularJS

AngularJS 简介AngularJS 是由 Google 发起的一款开源的前端 MVC 脚本框架,既适合做普通 WEB 应用也可以做 SPA(单页面应用,所有的用户操作都在一个页面中完成).与同为 MVC 框架的 Dojo 的定位不同,AngularJS 在功能上更加轻量,而相比于 jQuery,AngularJS 又帮您省去了许多机械的绑定工作.在一些对开发速度要求高,功能模块不需要太丰富的非企业级 WEB 应用上,AngularJS 是一个非常好的选择.AngularJS 最为复杂同时