zoukankan      html  css  js  c++  java
  • Android控件状态依赖框架

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

    Demo图

    设定图中

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

    输入框有三种状态:

    1. 待输入;
    2. 待校验;
    3. 校验成功。

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

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

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

    使用方法:

    1. 布局文件引用WatchEditTextWatchButton
    <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不是常量(可参考ButterKnifeLibrary Module的支持采用R2的原因),这里采用了tag的方式。

    1. 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定义控件名称,ViewDependencydependency指定其依赖的控件tag
    3. 直接执行onClickonEditorAction(修改状态)

    @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:annotationstateview

    1. annotation中定义ViewNameViewDependency注解,分别用于WatchEditTextWatchButtonViewName指定WatchEditText控件在业务中的名称,ViewDependency指定WatchButton依赖的WatchEditText控件;
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ViewDependency {
    
        ViewName name() default @ViewName;
    
        String[] dependency() default {};
    }
    
    1. state中通过状态模式定义EnterVerifyComplete,其基类为抽象类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;
        }
    }
    
    1. WatchEditTextWatchButton定义控件的依赖关系。WatchEditText实现ViewState接口,其包含三种状态的转换方法。
    public interface ViewState {
        void enter();
        void verify();
        void complete();
    }
    

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

  • 相关阅读:
    route-over VS mesh-under
    IOS算法(三)之插入排序
    GitHub学习笔记
    Python-面向对象 (二 继承)
    POJ 3518 Prime Gap(素数题)
    struts2的总体回想(ACTION、拦截器、值栈、OGNL表达式、ModelDriven方案等)
    first move advantage_百度搜索
    【绿茶书情】:《SOHO小报》和《凤…
    潘石屹的SOHO小报猝死
    ASP.NET Hashtable输出JSON格式数据
  • 原文地址:https://www.cnblogs.com/younghao/p/6617002.html
Copyright © 2011-2022 走看看