Java技巧分享之利用RxJava打造可观测数据RxLiveData

 更新时间:2023年06月09日 15:22:24   作者:乐征skyline  
这篇文章主要来和大家分享一个Java技巧,那就是利用RxJava打造可观测数据RxLiveData,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

1. 问题场景

在实际工作中,我们经常需要在不同类对象之间、不同模块之间共享数据,而这些数据通常是可改动的,那么就可能发生一个问题:当数据变动时,相关对象或模块并不知道,没有及时更新数据。这时候,我们希望数据改变时可以通知其他模块同步更新,实现一个类似数据之间联动的效果。最容易想到的应该就是监听回调的观察者模式,下面给出一种以前见过的、不太优雅的实现:

class User {
    //...... Java Bean 的字段略
}
interface Listener {
    void onUserUpdated(User user);
}
class UserManager {
    private static UserManager manager = new UserManager();
    private UserManager() {
    }
    public static UserManager getInstance() {
        return manager;
    }
    private User user;
    private List<Listener> listeners = new LinkedList<>();
    public void addUserListener(Listener listener) {
        listeners.add(listener);
    }
    public void removeUserListener(Listener listener) {
        listeners.remove(listener);
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
        for (Listener listener : listeners) {
            listener.onUserUpdated(this.user);
        }
    }
}

这种方式有以下缺点:

  • 不具备复用性(每次添加新的数据都要把回调监听重新实现一遍);
  • 增加内存溢出的风险(调用addUserListener的人可能忘记调用removeUserListener);
  • setter方法的污染(做了多余的事情)。

面对这样的问题,RxJava、JDK中的Observable和Flow API还有Android里的LiveData都给出了可用的实现方式,在实际开发中,感觉并不是那么方便。而本文要介绍的是我利用RxJava打造一个更加方便的可观测对象工具类--RxLiveData(代码见最底部)。

2. 使用示例

先来看一个比较短的完整示例:

/* 测试用的 Java Bean 数据类*/
class User {
    //...... Java Bean 的字段略
}
/* 一个单例 */
class UserManager {
    private static final UserManager manager = new UserManager();
    private UserManager() {
    }
    public static UserManager getInstance() {
        return manager;
    }
    private final RxLiveData<User> userData = new RxLiveData<>();
    public RxLiveData<User> getUserData() {
        return userData;
    }
}
class A {
    public void init() {
        //订阅可观测对象,使得数据发生改变时可以被回调
        UserManager.getInstance().getUserData().getObservable()
                .subscribe((User user) -> {//使用lambda版
                    update(user);// 每次用户信息改变,这里会被调用
                });
        update(UserManager.getInstance().getUserData().getValue());
    }
    private void update(User user) {
        System.out.println("user changed");
    }
}
class B{
    public B() {
        UserManager.getInstance().getUserData().getObservable().subscribe(this::update);//方法引用版
    }
    private void update(User user) {
        System.out.println("user changed");
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {
        A a = new A();
        a.init();
        B b = new B();
        //更新UserManager中的数据,这时候A和B中的对应方法会被调用
        UserManager.getInstance().getUserData().postData(new User());
    }
}

这里模拟UserManager的数据在AB类的对象之间共享,当UserManager的内容发生改变时,可以通知到AB,执行相应操作。

这时如果还想给UserManager增加一个数据,例如一个long类型的time,只需要按照下面这样添加一个属性和一个getter方法就可以了:

private final RxLiveData<Long> timeData = new RxLiveData<>();
public RxLiveData<Long> getTimeData() {
    return timeData;
}

如果是在Android应用开发中,还可以借助RxAndroid和RxLifecycle的功能,来控制回调的执行线程并在界面销毁时取消订阅,例如:

userManager.getUserData().getObservable()
        .compose(bindUntilEvent(ActivityEvent.DESTROY))//指定在onDestroy回调时取消订阅
        .observeOn(AndroidSchedulers.mainThread())//指定主线程
        .subscribe(user -> {
        }, Throwable::printStackTrace);

3. 主要方法介绍

3.1 getObservable 方法

方法签名public Observable<T> getObservable()

这个方法用于获取RxJava的Observable,进而对数据进行订阅,还可以得到RxJava相关功能的支持(例如,Stream 操作,指定线程,控制生命周期等等)。

3.2 postData 方法

方法签名public void postData(T value)

这个方法用于更新数据。它会更新存在在当前RxLiveData对象中的数据,并通过RxJava的ObservableEmitter触发观察者的回调。

注意:当参数为null时,由于RxJava会对null抛出异常,所以这里的实现方式是在判断为null的时候只存储数据,不触发观察者的回调。

3.3 getValue 方法

方法签名public T getValue()

这个方法仅用于获得存在在当前RxLiveData中的数据。

3.4 optValue 方法

方法签名public Optional<T> optValue()

getValue方法的Optional版本。

4. 完整实现

import io.reactivex.rxjava3.core.Observable;//如果用的是RxJava2的请改为该版本的包名
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.disposables.Disposable;
import java.util.Optional;
public class RxLiveData<T> {
    private final Observable<T> observable;
    private Disposable disposable;
    private T value;
    private ObservableEmitter<T> emitter;
    public RxLiveData() {
        observable = Observable
                .create((ObservableEmitter<T> emitter) -> this.emitter = emitter)
                .publish()
                .autoConnect(0, disposable -> this.disposable = disposable);
    }
    public Observable<T> getObservable() {
        return observable;
    }
    public void postData(T value) {
        this.value = value;
        if (emitter != null && value != null) {
            emitter.onNext(value);
        }
    }
    public T getValue() {
        return value;
    }
    public Optional<T> optValue() {
        return Optional.ofNullable(value);
    }
}

到此这篇关于Java技巧分享之利用RxJava打造可观测数据RxLiveData的文章就介绍到这了,更多相关Java RxJava可观测数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于SpringBoot实现验证码功能的代码及思路

    基于SpringBoot实现验证码功能的代码及思路

    SpringBoot技术是目前市面上从事JavaEE企业级开发过程中使用量最大的技术,下面这篇文章主要给大家介绍了如何基于SpringBoot实现验证码功能的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • Spring中RedisTemplate使用方法详解

    Spring中RedisTemplate使用方法详解

    Spring封装了一个比较强大的模板,也就是redisTemplate,方便在开发的时候操作Redis缓存,这篇文章主要给大家介绍了关于Java中RedisTemplate使用方法的相关资料,需要的朋友可以参考下
    2023-12-12
  • 分析讲解SpringMVC注解配置如何实现

    分析讲解SpringMVC注解配置如何实现

    这篇文章主要介绍了本文要介绍用注解方式代替web.xml与SpringMVC的配置文件,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • dubbo如何设置连接zookeeper权限

    dubbo如何设置连接zookeeper权限

    这篇文章主要介绍了dubbo如何设置连接zookeeper权限问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • java保证一个方法只能执行一次的问题

    java保证一个方法只能执行一次的问题

    这篇文章主要介绍了java保证一个方法只能执行一次的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • SpringBoot项目yml配置文件不自动提示解决方案

    SpringBoot项目yml配置文件不自动提示解决方案

    这篇文章主要介绍了SpringBoot项目配置文件.yaml/.yml文件编写时没有自动提示的解决方案,文章通过图文结合的方式给大家讲解的非常详细,需要的朋友可以参考下
    2024-06-06
  • 前端如何调用后端接口进行数据交互详解(axios和SpringBoot)

    前端如何调用后端接口进行数据交互详解(axios和SpringBoot)

    一般来讲前端不会给后端接口,而是后端给前端接口的情况比较普遍,下面这篇文章主要给大家介绍了关于前端如何调用后端接口进行数据交互的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • 解析HashMap中的put方法执行流程

    解析HashMap中的put方法执行流程

    在Java集合中,HashMap的重要性不言而喻,作为一种存储键值对的数据结构,它在日常开发中有着非常多的应用场景,也是面试中的高频考点,本篇文章就来分析一下HashMap集合中的put方法
    2021-12-12
  • 关于解决雪花算法生成的ID传输前端后精度丢失问题

    关于解决雪花算法生成的ID传输前端后精度丢失问题

    这篇文章主要介绍了关于解决雪花算法生成的ID传输前端后精度丢失问题,雪花算法生成的ID传输到前端时,会出现后三位精度丢失,本文提供了解决思路,需要的朋友可以参考下
    2023-03-03
  • java中断机制实例讲解

    java中断机制实例讲解

    这篇文章主要介绍了java中断机制实例讲解,用了风趣幽默的讲法,有对这方面不太懂的同学可以研究下
    2021-01-01

最新评论