详解Android控件状态依赖框架

作者:yhthu 时间:2023-07-01 10:01:06 

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

详解Android控件状态依赖框架

设定图中

  • 确认操作依赖于商品编码和储位的状态

  • 跳过操作不依赖于输入状态

  • 登记差异操作依赖于储位和数量的状态

输入框有三种状态:

  • 待输入;

  • 待校验;

  • 校验成功。

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

如果在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,控件状态,依赖框架
0
投稿

猜你喜欢

  • Android 事件分发详解及示例代码

    2023-09-08 05:18:45
  • java Class.getSimpleName() 详解及用法

    2021-06-26 16:35:41
  • 详解AOP与Filter拦截请求打印日志实用例子

    2021-09-26 22:03:10
  • C#中Array与ArrayList用法及转换的方法

    2021-07-18 13:13:23
  • C++对string进行大小写转换操作方法

    2023-11-03 04:32:59
  • Java C++题解leetcode 1684统计一致字符串的数目示例

    2023-04-23 09:06:31
  • C#获取图片文件扩展名的方法

    2022-03-06 04:27:43
  • Java8如何将Array转换为Stream的实现代码

    2022-09-15 06:41:31
  • Kryo框架使用方法代码示例

    2021-05-30 15:46:05
  • 学习Java的Date、Calendar日期操作

    2023-09-04 22:26:38
  • C#调用摄像头实现拍照功能的示例代码

    2023-02-14 16:21:41
  • C# Winfrom实现Skyline画直线功能的示例代码

    2023-04-24 12:41:48
  • Android编程开发之ScrollView嵌套GridView的方法

    2023-02-16 08:21:00
  • android 类似微信的摇一摇功能实现思路及代码

    2022-09-16 03:45:36
  • springboot多租户设计过程图解

    2021-12-21 08:09:45
  • Java实现数组转字符串及字符串转数组的方法分析

    2022-04-14 10:53:44
  • Android SurfaceView画板操作

    2022-07-10 15:12:23
  • Java实现简易生产者消费者模型过程解析

    2023-12-03 01:33:26
  • Java设计模式之命令模式

    2022-06-17 22:49:07
  • Android编程实现图片的浏览、缩放、拖动和自动居中效果

    2021-06-04 15:01:39
  • asp之家 软件编程 m.aspxhome.com