java - 如何在没有 null 的情况下处理链中可能的空值(无模型技巧)?

标签 java android rx-java2

我正在尝试在以前的 MVC 项目中添加 RX And​​roid 包库,其中我正在尝试处理 API 响应到 Activity Controller 的值,并传递一些 Controller 来对其执行一些附加操作。

API 的可能性是该值可能为空/可选/null,在这种情况下, Controller 会尝试从缓存存储中获取该值,该值也可能处于相同的条件下,最后将其传递给 Controller ,根据值,它将执行一些初始化操作,或尝试使用相同的机制进行另一个 API 调用,检查该响应,然后选择如何初始化 Activity 。

示例代码(签名错误)

在 API 中:

Maybe<User> getUser(){
    //...
}

在 Controller 中:

Single<User> getUser(){
    return API.getUser().switchIfEmpty(() -> Cache.getUser());
}

Activity 中:

Disposable d = getUser().subscribe(user -> { if(user != null) init(user); else checkGuest();  } );

//...

void checkGuest(){
    Disposable d = getGuest().subscribe(guest -> { init(guest) } );
}

所有这一切都将非常酷和顺利,除了考虑一下,RX Java 无法处理空值。我们可以说,从 Java 8 开始,我们就试图克服 null 值,转而使用可选值(真的吗?!?!?),因此 Empty/Maybe 模式是合适的。

那么,让我们试试这个...

在 API 中:

Maybe<User> getUser(){
    //...
}

在 Controller 中:

Single<User> getUser(){
    return API.getUser().switchIfEmpty(() -> Cache.getUser()).switchIfEmpty(() -> ???);
}

Activity 中:

Disposable d = getUser().subscribe(user -> { if(user != ???) init(user); else checkGuest();  } );

//...

void checkGuest(){
    Disposable d = getGuest().subscribe(guest -> { init(guest) } );
}

我想说,我讨厌并且根本无法接受修改我的模型来添加某种附加属性,该属性会将实例标记为 Rx null 实例,也因为,这是一个绝对的与任何其他方法一样,违反完整性将强制检查该属性,并带有大量样板。

解决方案:

  • 1 我试图通过在订阅的错误可调用中使用单个自定义异常条件检查来处理这个问题,以决定在链传播中继续执行下一个方法,混合函数式和响应式(Reactive)编程。

  • 2 我必须修改我的模型,并使用 RX Nulled 实例来代替我们喜爱的 null 值,但当然,也是因为我正在使用 Realm,而且我什至无法使用多态性,而且,正如之前所说,它违反了完整性。

  • 3 理想情况下,我想保留链模式,并通过使用 Maybe 能够执行链路径(如果先前的值为空)或另一个链路径(如果该值不是空)。

如果有人愿意提出选项 3,我会很高兴,这会让我在第一次看到 ReactiveX 示例时惊叹不已。

最佳答案

经过一番搜索,我发现最终最好的解决方案实际上是......坚持......使用Java 8可选!

首先,这允许像往常一样保留良好的旧通用空检查模式,这样我们就不需要真正忘记它,而且还可以继续新技术的发展,从而符合我们喜欢新的标准,因此要遵循新的 Java 规范。

这也是一个“非”向后兼容性中断,因为在 Android 中,我们可以依靠一些向后移植依赖项来在 API 级别 24 之前启用此功能。

// support for optionals
compile "net.sourceforge.streamsupport:streamsupport:1.5.1"

此外,这允许使用链式操作、条件、ReactiveX 和单个值,正如我们程序员喜欢的那样。

    public Single<Optional<Model>> getMyModel(boolean offlineFallback) {

    return apiInterface.getModel()
            .map( model -> {
                if( model.isPresent() ){

                    MyModel serverMyModel = model.get();
                    MyModel savedMyModel = databaseRepository.getMyModel();
                    if( serverMyModel != savedMyModel ){
                        serverMyModel.setMyAttribute(true);
                        databaseRepository.saveMyModel( serverMyModel );
                    }
                    return java8.util.Optional.ofNullable( serverMyModel );

                }else{

                    if(offlineFallback){
                        MyModel MyModel = databaseRepository.getMyModel();
                        if(MyModel != null){
                            return java8.util.Optional.ofNullable(MyModel);
                        }
                    }
                    return Optional.empty();

                }
            });
}

这不是很好吗?

关于java - 如何在没有 null 的情况下处理链中可能的空值(无模型技巧)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56337717/

相关文章:

java - 如何在 RxJava2 中并行执行消费者?

android - Kotlin Coroutines 中是否有 RxJava 主题的类似物?

android - 在 onDoNext 和 doOnCompleted 方法中难以设置 View

java - 为给定的唯一数字列表/集合/数组生成唯一 ID

java - SimpleDateFormat 类中的月份问题

Android:设备长时间处于空闲状态后,Socket 进入僵尸状态

android - Admob 广告无法在 Android 上展示,但可以在 iOS 上展示 -- Flutter

java - 在 Java 中读取 CLOB 到 String 和 String 到 CLOB 的最有效解决方案?

java - 调用图表引擎图表时 Android 应用程序崩溃

java - Java 是否有编译器指令来内联方法?