最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java技巧分享之利用RxJava打造可觀測(cè)數(shù)據(jù)RxLiveData

 更新時(shí)間:2023年06月09日 15:22:24   作者:樂(lè)征skyline  
這篇文章主要來(lái)和大家分享一個(gè)Java技巧,那就是利用RxJava打造可觀測(cè)數(shù)據(jù)RxLiveData,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

1. 問(wèn)題場(chǎng)景

在實(shí)際工作中,我們經(jīng)常需要在不同類(lèi)對(duì)象之間、不同模塊之間共享數(shù)據(jù),而這些數(shù)據(jù)通常是可改動(dòng)的,那么就可能發(fā)生一個(gè)問(wèn)題:當(dāng)數(shù)據(jù)變動(dòng)時(shí),相關(guān)對(duì)象或模塊并不知道,沒(méi)有及時(shí)更新數(shù)據(jù)。這時(shí)候,我們希望數(shù)據(jù)改變時(shí)可以通知其他模塊同步更新,實(shí)現(xiàn)一個(gè)類(lèi)似數(shù)據(jù)之間聯(lián)動(dòng)的效果。最容易想到的應(yīng)該就是監(jiān)聽(tīng)回調(diào)的觀察者模式,下面給出一種以前見(jiàn)過(guò)的、不太優(yōu)雅的實(shí)現(xiàn):

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);
        }
    }
}

這種方式有以下缺點(diǎn):

  • 不具備復(fù)用性(每次添加新的數(shù)據(jù)都要把回調(diào)監(jiān)聽(tīng)重新實(shí)現(xiàn)一遍);
  • 增加內(nèi)存溢出的風(fēng)險(xiǎn)(調(diào)用addUserListener的人可能忘記調(diào)用removeUserListener);
  • setter方法的污染(做了多余的事情)。

面對(duì)這樣的問(wèn)題,RxJava、JDK中的Observable和Flow API還有Android里的LiveData都給出了可用的實(shí)現(xiàn)方式,在實(shí)際開(kāi)發(fā)中,感覺(jué)并不是那么方便。而本文要介紹的是我利用RxJava打造一個(gè)更加方便的可觀測(cè)對(duì)象工具類(lèi)--RxLiveData(代碼見(jiàn)最底部)。

2. 使用示例

先來(lái)看一個(gè)比較短的完整示例:

/* 測(cè)試用的 Java Bean 數(shù)據(jù)類(lèi)*/
class User {
    //...... Java Bean 的字段略
}
/* 一個(gè)單例 */
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() {
        //訂閱可觀測(cè)對(duì)象,使得數(shù)據(jù)發(fā)生改變時(shí)可以被回調(diào)
        UserManager.getInstance().getUserData().getObservable()
                .subscribe((User user) -> {//使用lambda版
                    update(user);// 每次用戶(hù)信息改變,這里會(huì)被調(diào)用
                });
        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中的數(shù)據(jù),這時(shí)候A和B中的對(duì)應(yīng)方法會(huì)被調(diào)用
        UserManager.getInstance().getUserData().postData(new User());
    }
}

這里模擬UserManager的數(shù)據(jù)在AB類(lèi)的對(duì)象之間共享,當(dāng)UserManager的內(nèi)容發(fā)生改變時(shí),可以通知到AB,執(zhí)行相應(yīng)操作。

這時(shí)如果還想給UserManager增加一個(gè)數(shù)據(jù),例如一個(gè)long類(lèi)型的time,只需要按照下面這樣添加一個(gè)屬性和一個(gè)getter方法就可以了:

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

如果是在Android應(yīng)用開(kāi)發(fā)中,還可以借助RxAndroid和RxLifecycle的功能,來(lái)控制回調(diào)的執(zhí)行線(xiàn)程并在界面銷(xiāo)毀時(shí)取消訂閱,例如:

userManager.getUserData().getObservable()
        .compose(bindUntilEvent(ActivityEvent.DESTROY))//指定在onDestroy回調(diào)時(shí)取消訂閱
        .observeOn(AndroidSchedulers.mainThread())//指定主線(xiàn)程
        .subscribe(user -> {
        }, Throwable::printStackTrace);

3. 主要方法介紹

3.1 getObservable 方法

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

這個(gè)方法用于獲取RxJava的Observable,進(jìn)而對(duì)數(shù)據(jù)進(jìn)行訂閱,還可以得到RxJava相關(guān)功能的支持(例如,Stream 操作,指定線(xiàn)程,控制生命周期等等)。

3.2 postData 方法

方法簽名public void postData(T value)

這個(gè)方法用于更新數(shù)據(jù)。它會(huì)更新存在在當(dāng)前RxLiveData對(duì)象中的數(shù)據(jù),并通過(guò)RxJava的ObservableEmitter觸發(fā)觀察者的回調(diào)。

注意:當(dāng)參數(shù)為null時(shí),由于RxJava會(huì)對(duì)null拋出異常,所以這里的實(shí)現(xiàn)方式是在判斷為null的時(shí)候只存儲(chǔ)數(shù)據(jù),不觸發(fā)觀察者的回調(diào)。

3.3 getValue 方法

方法簽名public T getValue()

這個(gè)方法僅用于獲得存在在當(dāng)前RxLiveData中的數(shù)據(jù)。

3.4 optValue 方法

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

getValue方法的Optional版本。

4. 完整實(shí)現(xiàn)

import io.reactivex.rxjava3.core.Observable;//如果用的是RxJava2的請(qǐng)改為該版本的包名
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);
    }
}

到此這篇關(guān)于Java技巧分享之利用RxJava打造可觀測(cè)數(shù)據(jù)RxLiveData的文章就介紹到這了,更多相關(guān)Java RxJava可觀測(cè)數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 實(shí)現(xiàn)一個(gè)規(guī)則引擎的可視化具體方案

    實(shí)現(xiàn)一個(gè)規(guī)則引擎的可視化具體方案

    項(xiàng)目原因需要用到規(guī)則引擎,但是發(fā)現(xiàn)大部分不可以自由的進(jìn)行規(guī)則定義,通過(guò)不斷嘗試變換關(guān)鍵字在搜索引擎搜索,最終在stackoverflow找到了一個(gè)探討這個(gè)問(wèn)題的帖子,特此將帖子中提到的方案分享一下,如果你跟我一樣在研究同樣的問(wèn)題,也許對(duì)你有用
    2021-04-04
  • 一文總結(jié)Java實(shí)現(xiàn)TXT轉(zhuǎn)PDF的三種高效方案

    一文總結(jié)Java實(shí)現(xiàn)TXT轉(zhuǎn)PDF的三種高效方案

    將 TXT 文本轉(zhuǎn)換為 PDF 并不繁瑣,本篇指南將介紹根據(jù)三種實(shí)用的轉(zhuǎn)換技巧,包括手動(dòng)操作、在線(xiàn)工具和程序化自動(dòng)處理,助你輕松搞定文檔遷移,希望對(duì)大家有所幫助
    2026-02-02
  • 新手也能看懂的SpringBoot異步編程指南(簡(jiǎn)單易懂)

    新手也能看懂的SpringBoot異步編程指南(簡(jiǎn)單易懂)

    這篇文章主要介紹了新手也能看懂的SpringBoot異步編程指南(簡(jiǎn)單易懂),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • MyEclipse打開(kāi)文件跳轉(zhuǎn)到notepad打開(kāi)問(wèn)題及解決方案

    MyEclipse打開(kāi)文件跳轉(zhuǎn)到notepad打開(kāi)問(wèn)題及解決方案

    windows系統(tǒng)打開(kāi)README.md文件,每次都需要右鍵選擇notepad打開(kāi),感覺(jué)很麻煩,然后就把README.md文件打開(kāi)方式默認(rèn)選擇了notepad,這樣每次雙擊就能打開(kāi),感覺(jué)很方便,這篇文章主要介紹了MyEclipse打開(kāi)文件跳轉(zhuǎn)到notepad打開(kāi)問(wèn)題,需要的朋友可以參考下
    2024-03-03
  • Java中日期的加減&String Date Calendar的相互轉(zhuǎn)換方式

    Java中日期的加減&String Date Calendar的相互轉(zhuǎn)換方式

    這篇文章主要介紹了Java中日期的加減&String Date Calendar的相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • 淺談Spring單例Bean與單例模式的區(qū)別

    淺談Spring單例Bean與單例模式的區(qū)別

    這篇文章主要介紹了淺談Spring單例Bean與單例模式的區(qū)別,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2017-12-12
  • RocketMQ中消費(fèi)者的消費(fèi)進(jìn)度管理

    RocketMQ中消費(fèi)者的消費(fèi)進(jìn)度管理

    這篇文章主要介紹了RocketMQ中消費(fèi)者的消費(fèi)進(jìn)度管理,業(yè)務(wù)實(shí)現(xiàn)消費(fèi)回調(diào)的時(shí)候,當(dāng)且僅當(dāng)此回調(diào)函數(shù)返回ConsumeConcurrentlyStatus.CONSUME_SUCCESS ,RocketMQ才會(huì)認(rèn)為這批消息(默認(rèn)是1條)是消費(fèi)完成的,需要的朋友可以參考下
    2023-10-10
  • IDEA配置Tomcat后,控制臺(tái)tomcat?catalina?log出現(xiàn)亂碼問(wèn)題

    IDEA配置Tomcat后,控制臺(tái)tomcat?catalina?log出現(xiàn)亂碼問(wèn)題

    本文介紹了如何通過(guò)設(shè)置Tomcat和IDEA的編碼格式來(lái)解決編碼問(wèn)題,首先嘗試修改Tomcat的logging.properties文件中的編碼設(shè)置,如果未解決問(wèn)題,則調(diào)整IDEA的編碼設(shè)置,通過(guò)修改vmoptions文件來(lái)全局設(shè)置IDEA的編碼格式,作者分享了個(gè)人成功解決問(wèn)題的方法和步驟,供其他開(kāi)發(fā)者參考
    2024-09-09
  • java中接口冪等性的五種實(shí)現(xiàn)方法

    java中接口冪等性的五種實(shí)現(xiàn)方法

    在java中保證接口冪等性,即多次調(diào)用同一接口產(chǎn)生與單次調(diào)用相同的結(jié)果,不會(huì)引發(fā)副作用,需要結(jié)合業(yè)務(wù)場(chǎng)景選擇合適的方案,下面就來(lái)介紹五種實(shí)現(xiàn)方法,感興趣的可以了解一下
    2025-09-09
  • Java 調(diào)用Restful API接口的幾種方式(HTTPS)

    Java 調(diào)用Restful API接口的幾種方式(HTTPS)

    這篇文章主要介紹了Java 調(diào)用Restful API接口的幾種方式(HTTPS),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02

最新評(píng)論

东山县| 辽源市| 宁蒗| 丰县| 岫岩| 英德市| 大同县| 海淀区| 延川县| 安吉县| 瑞丽市| 清原| 上林县| 延寿县| 郸城县| 大方县| 抚远县| 神木县| 三门峡市| 嘉荫县| 南川市| 奇台县| 高雄县| 海原县| 灵璧县| 河东区| 颍上县| 临城县| 安徽省| 阳城县| 简阳市| 平湖市| 兴文县| 溧阳市| 九寨沟县| 晴隆县| 绍兴市| 郁南县| 通州市| 桑日县| 建宁县|