欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android控件状态依赖框架

程序员文章站 2022-10-14 14:16:55
在生产型android客户端软件(企业级应用)开发中,界面可能存在多个输入(edittext)和多个操作(motionevent和keyevent),且操作依赖于输入的状态...

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

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