• ViewOptional:一个安全便利的查找View的工具


    虽然现在开发Android界面DataBindingViewBinding已经普及开来,但是很多的老项目或者一些特殊的场合可能还会用findViewById这种最原始的写法,但这种写法比较麻烦,又不太安全,本文就分享一个简单的用于安全、便利的获取View的工具–ViewOptional

    1. 使用示例

    View root = null;
    //获取对应View,再进行对应操作
    ViewOptional<View> vo1 = ViewOptional.find(root, R.id.tvName);
    View view1 = vo1.get();
    boolean isEmpty = vo1.isEmpty();
    boolean isPresent = vo1.isPresent();
    boolean isTextView = vo1.isInstanceOf(TextView.class);
    vo1.ifPresent((View view) -> {
        //doSomething
    });
    vo1.ifInstanceOf(TextView.class, (TextView tvName) -> {
        //doSomething
    });
    
    //利用方法链直接操作
    ViewOptional.find(root, R.id.tvName).ifPresent(view -> {
        //doSomething
    });
    
    //构造时提供类型参数,来自动转换类型
    ViewOptional.find((root, R.id.tvName, TextView.class)
            .ifPresent((TextView tvName) -> {
                //doSomething
            });
    
    //提供备选id,如果第一个找不到对应View,就依次尝试备选的
    ViewOptional.find(root, TextView.class, R.id.tvName, R.id.tvUserName, R.id.tvAccountName)
            .ifPresent((TextView tvName) -> {
                //doSomething
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2. 接口说明

    • 静态工厂方法 ViewOptional find(@Nullable View rootView, @IdRes int id):从一个控件rootView中查找指定id的View,来构造对应ViewOptional

    • 静态工厂方法 ViewOptional find(@Nullable View rootView, @IdRes int id, Class tClass):从一个控件rootView中查找指定id的View,尝试转换为指定类型,来构造对应ViewOptional

    • 静态工厂方法 ViewOptional find(@Nullable View rootView, Class tClass, @IdRes int id, int... defIds):从一个控件rootView中查找指定id的View,尝试转换为指定类型,来构造对应ViewOptional,如果第一个id没有对应的View就依次尝试后面的id;

    • 静态工厂方法 ViewOptional of(@Nullable T view):从已有的变量来构建ViewOptional

    • 方法V get():获取对应的View,如果不存在,抛出异常;

    • 方法boolean isEmpty:判断当前ViewOptional是否为空;

    • 方法boolean isPresent():判断当前ViewOptional是否有值;

    • 方法 boolean isInstanceOf(Class vcClass):判断当前的View是否为指定类型;

    • 方法void ifPresent(Consumer consumer):如果有值,则执行对应consumer;

    • 方法void ifPresent(Consumer consumer, Runnable elseRunnable):如果有值,则执行对应consumer,否则,就执行elseRunnable

    • 方法 void ifInstanceOf(Class avClass, Consumer consumer):如果控件是指定类型,则执行对应consumer;

    • 方法 void ifInstanceOf(Class avClass, Consumer consumer, Runnable elseRunnable):如果控件是指定类型,则执行对应consumer,否则,就执行elseRunnable

    • 方法V orElse(V other):如果有值,就返回对应View,否则,返回默认值other

    • 方法V orElseGet(Supplier other):如果有值,就返回对应View,否则,只用Supplier返回的默认值;

    3. 完整实现

    public class ViewOptional<V extends View> {
        private V view;
    
        private ViewOptional() {
        }
    
        private ViewOptional(V view) {
            this.view = view;
        }
    
        public static <T extends View> ViewOptional<T> find(@Nullable View rootView, @IdRes int id, Class<T> tClass) {
            if (rootView == null) {
                return of(null);
            } else {
                View view = rootView.findViewById(id);
                if (tClass.isInstance(view)) {
                    return of(tClass.cast(view));
                } else {
                    return of(null);
                }
            }
        }
    
        public static <T extends View> ViewOptional<T> find(@Nullable View rootView, @IdRes int id) {
            if (rootView == null) {
                return of(null);
            } else {
                return of(rootView.findViewById(id));
            }
        }
    
        public static <T extends View> ViewOptional<T> find(@Nullable View rootView, Class<T> tClass, @IdRes int id, int... defIds) {
            if (rootView == null) {
                return of(null);
            } else {
                View view = rootView.findViewById(id);
                if (tClass.isInstance(view)) {
                    return of(tClass.cast(view));
                } else if (defIds != null) {
                    for (int defId : defIds) {
                        view = rootView.findViewById(defId);
                        if (tClass.isInstance(view)) {
                            return of(tClass.cast(view));
                        }
                    }
                    return of(null);
                } else {
                    return of(null);
                }
            }
        }
    
        public static <T extends View> ViewOptional<T> of(@Nullable T view) {
            return new ViewOptional<>(view);
        }
    
        public V get() {
            if (view == null) {
                throw new NoSuchElementException("No value present");
            }
            return view;
        }
    
        public boolean isEmpty() {
            return view == null;
        }
    
        public boolean isPresent() {
            return view != null;
        }
    
        public <AV extends View> boolean isInstanceOf(Class<AV> vcClass) {
            return vcClass.isInstance(view);
        }
    
        public void ifPresent(Consumer<? super V> consumer) {
            if (view != null)
                consumer.accept(view);
        }
    
        public void ifPresent(Consumer<? super V> consumer, Runnable elseRunnable) {
            if (view != null)
                consumer.accept(view);
            else
                elseRunnable.run();
        }
    
        public <AV extends View> void ifInstanceOf(Class<AV> avClass, Consumer<? super AV> consumer) {
            if (isInstanceOf(avClass)) {
                consumer.accept(avClass.cast(view));
            }
        }
    
        public <AV extends View> void ifInstanceOf(Class<AV> avClass, Consumer<? super AV> consumer, Runnable elseRunnable) {
            if (isInstanceOf(avClass)) {
                consumer.accept(avClass.cast(view));
            } else {
                elseRunnable.run();
            }
        }
    
        public V orElse(V other) {
            return view != null ? view : other;
        }
    
        public V orElseGet(Supplier<? extends V> other) {
            return view != null ? view : other.get();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
  • 相关阅读:
    记录一次线上fullgc问题排查过程
    智能垃圾设备监测系统
    【代码片段】C#程序Json 配置文件读取,当配置文件出错重新创建默认的配置文件
    【Vue3+TS】Composition API(一)
    python经典100题之判断今年的第几天
    springboot基于微信小程序的校园外卖系统毕业设计源码091024
    OPENCV图像和视频处理
    在kubernetes中对pod使用tcpdump+wireShark进行抓包
    使用 Vue3 构建 Web Components
    4、FFmpeg命令行操作7
  • 原文地址:https://blog.csdn.net/zssrxt/article/details/126331828