2016-02-20 19 views
2

这有可能会有点复杂,我与观测量和RX模式经历没有那么多包涵:订阅可观察到的,而不会触发它,然后将它传递出去

假设你已经有了一些任意返回一个Observable的SDK方法。你从一个类中消费方法 - 除其他外 - 负责检索数据,并在这样做的时候执行一些缓存,所以我们称之为DataProvider。然后你有另一个班想要访问由DataProvider提供的数据。现在我们将其称为Consumer。所以我们有我们的设置。

所有模式朋友的注意事项:我知道这不是MVP,它仅仅是一个类似的例子,但是我在我的应用程序中遇到了更复杂的问题。

话虽这么说,在科特林般的伪代码所描述的情况是这样的:

class Consumer(val provider: DataProvider) { 
    fun logic() { 
     provider.getData().subscribe(...) 
    } 
} 

class DataProvider(val sdk: SDK) { 
    fun getData(): Consumer { 
     val observable = sdk.getData() 
     observable.subscribe(/*cache data as it passes through*/) 
     return observable 
    } 
} 

class SDK { 
    fun getData(): Observable { 
     return fetchDataFromNetwork() 
    } 
} 

的问题是,在调用sdk.subscribe()DataProvider我已经触发了可观测的subscribe()方法我不想要。我想让DataProvider静静地听 - 在这个例子中,触发应该由Consumer完成。

那么这个问题最好的RX兼容解决方案是什么?上述伪代码中概述的明确不是由于各种原因,其中之一是在Consumer已订阅Observable之前过早触发网络请求。在拨打DataProvider中的subscribe()之前,我已尝试使用publish().autoComplete(2),但这似乎不是执行此类事情的标准方法。它只是觉得哈克。通过SO卓越的“相关”功能,我刚刚偶然发现了另一个指向不同方向的问题,但有一个解决方案,也可以在这里适用,即flatMap()。我之前就知道这一点,但从来没有真正使用它。对我来说似乎是一种可行的方式 - 您对此有何看法?

+1

必须有办法脱身,而无需调用'订阅()'内'的DataProvider# getData()',而是根据你需要使用其他操作符:'doOnNext()'如果你需要在链中修改事件而不修改事件,'map'或'flatMap'他们的方式等 – AndroidEx

+0

我不知道'doOnNext()' - 现在会试用它。 – ubuntudroid

+0

@AndroidEx'doOnNext()'成功了!请将您的评论转换为答案,我很乐意将其标记为已接受的答案。 – ubuntudroid

回答

1

如果高速缓存步骤不应该修改事件链中,doOnNext()运算符可以使用:

class DataProvider(val sdk: SDK) { 
    fun getData(): Observable<*> = sdk.getData().doOnNext(/*cache data as it passes through*/) 
} 
1

是的,flatMap可能是一个解决方案。此外,您可以将您的数据流分割成小Observables链:

public class DataProvider { 

    private Api api; 
    private Parser parser; 
    private Cache cache; 

    public Observable<List<User>> getUsers() { 
     return api.getUsersFromNetwork() 
       .flatMap(parser::parseUsers) 
       .map(cache::cacheUsers); 
    } 
} 

public class Api { 
    public Observable<Response> getUsersFromNetwork() { 
     //makes https request or whatever 
    } 
} 

public class Parser { 
    public Observable<List<User>> parseUsers(Response response) { 
     //parse users 
    } 
} 

public class Cache { 
    public List<User> cacheUsers(List<User> users) { 
     //cache users 
    } 
} 

这很容易测试,维护和替换的实现(与接口使用)。您还可以轻松地将额外的步骤插入到流中(例如,从服务器接收日志/转换/更改数据)。

另一个相当方便的操作者是map。基本上而不是Observable<Data>它只返回Data。它可以使你的代码更简单。

+0

我用@AndroidEx的解决方案到底。然而你的解决方案听起来也是可行的因此,我也会赞扬它。谢谢! – ubuntudroid