android-使用RxJava将本地数据与远程(或缓存)数据连接

android-使用RxJava将本地数据与远程(或缓存)数据连接,第1张

概述这是有效的代码,但是我有几个问题以及关于改进它的建议.我是RxJava的新手,我还没有完全了解如何将这些类型的可观察对象链接在一起.我有两个模型对象,ListItem和UserInfo.ListItems存在于本地数据库中,并且使用从ListItem提供的ID从服务器获取UserInfo.UserInfoWeb服务接受ID数

这是有效的代码,但是我有几个问题以及关于改进它的建议.我是RxJava的新手,我还没有完全了解如何将这些类型的可观察对象链接在一起.

我有两个模型对象,ListItem和UserInfo. ListItems存在于本地数据库中,并且使用从ListItem提供的ID从服务器获取UserInfo.

UserInfo Web服务接受ID数组,将为其返回UserInfo对象列表.

这段代码的流程如下:

>从数据库加载ListItems
>使用从数据库中获取的ListItem,检查内存中的缓存以查看是否已经获取了特定ListItem的UserInfo
>对于未缓存UserInfo的任何项目,请从网络中获取它们
>将获取的UserInfo对象放入缓存
>重新运行步骤2(方法为loadCachedUserInfo)
>将结果返回给订户

注意:仅当列表被视为isUserList时,才应为ListItem提取UserInfo对象.

这是代码:

fun itemsInList(List : ATList, parentValue : String? = null, searchString : String? = null, limit : Int = defaultFetchlimit, sortOrder: SortDescriptor? = null) : Observable<List<ATListItem>> {    return Observable.create<List<ATListItem>> { subscriber ->        val ListItems = ListItemsInList(List, parentValue = parentValue, searchString = searchString, limit = limit, sortOrder = sortOrder)        subscriber.onNext(ListItems)        subscriber.onCompleted()    }.flatMap { ListItems ->        if ( List.isUserList ) {            return@flatMap loadCachedUserInfo(ListItems, userIdindex = List.userIdindex!!)        }        return@flatMap Observable.just(ListItems)    }.flatMap { ListItems ->        if ( List.isUserList ) {            return@flatMap fetchUserInfoForListItems(ListItems, List.userIdindex!!, force = false)        }        return@flatMap Observable.just(ListItems)    }}fun loadCachedUserInfo(ListItems : List<ATListItem>, userIdindex : Int) : Observable<List<ATListItem>> {    return Observable.create<List<ATListItem>> { subscriber ->        for ( ListItem in ListItems ) {            ListItem.coreUserInfo = coreUserMap[ListItem.valueForAttributeIndex(userIdindex)?.tolowerCase()]        }        subscriber.onNext(ListItems)        subscriber.onCompleted()    }}fun fetchUserInfoForListItems(ListItems : List<ATListItem>, userIdindex: Int, force: Boolean) : Observable<List<ATListItem>> {    val itemsToFetch = if ( force ) ListItems else ListItems.filter { it.coreUserInfo == null }    val IDs = itemsToFetch.map { it.valueForAttributeIndex(userIdindex) ?: "" }.filter { !it.isEmpty() }    val records = hashMapOf("records" to IDs)    if ( itemsToFetch.count() == 0 ) {        return Observable.just(ListItems)    }    return RuntimeDataController.dataService.fetchCoreUserInfo(recordsMap = records)            .map { Json ->                val recordsArray = Json.arrayValue("records")                for ( i in 0..recordsArray.length() - 1) {                    val coreUserInfo = CoreUserInfo(recordsArray.getJsONObject(i))                    coreUserMap[coreUserInfo.username.tolowerCase()] = coreUserInfo                    coreUserMap[coreUserInfo.userID] = coreUserInfo                    coreUserInfo.externalUserID?.let { coreUserMap[it] = coreUserInfo }                }                return@map ListItems            }.flatMap { loadCachedUserInfo(ListItems, userIdindex = userIdindex) }}

用户可以通过调用以下命令来启动事件序列:

ListController.itemsInList(列表)

我对此代码的疑问是:

>当前,loadCachedUserInfo接收一个ListItem数组,并在与缓存项相关联后返回与可观察到的数组相同的数组.我觉得这很不对.我认为相反,此调用应仅返回与之关联的已缓存UserInfo的项目.但是,我需要继续将ListItem的完整数组传递给下一个方法

2.)我需要做其他工作来支持退订吗?

3.)这是类似的问题1.我的fetchUserInfoForListItems提取一个列表项数组,并在获取并通过cache方法重新运行它们之后返回与该列表项数组相同的Observable.这对我来说也感觉不正确.我希望该方法返回一个Observable< List< UserInfo>>.用于获取的对象.我不明白如何在itemsInList中然后将ListItems与新获取的UserInfo关联并返回这些ListItems的Observable.

编辑:写完这篇文章后,它给了我一些帮助.我可以将flatMap的调用包装到一个Observable.create中,其中可以包含我想从fetchUserInfoForListItems中取出的智能,让我解决问题#3.这是更新的代码:

 fun itemsInList(List : ATList, parentValue : String? = null, searchString : String? = null, limit : Int = defaultFetchlimit, sortOrder: SortDescriptor? = null) : Observable<List<ATListItem>> {    return Observable.create<List<ATListItem>> { subscriber ->        val ListItems = ListItemsInList(List, parentValue = parentValue, searchString = searchString, limit = limit, sortOrder = sortOrder)        subscriber.onNext(ListItems)        subscriber.onCompleted()    }.flatMap { ListItems ->        if ( List.isUserList ) {            return@flatMap loadCachedUserInfo(ListItems, userIdindex = List.userIdindex!!)        }        return@flatMap Observable.just(ListItems)    }.flatMap { ListItems ->        if ( List.isUserList ) {            return@flatMap Observable.create<List<ATListItem>> { subscriber ->                fetchUserInfoForListItems(ListItems, List.userIdindex!!, force = false).map { userInfoList ->                    for (coreUserInfo in userInfoList) {                        coreUserMap[coreUserInfo.username.tolowerCase()] = coreUserInfo                        coreUserMap[coreUserInfo.userID] = coreUserInfo                        coreUserInfo.externalUserID?.let { coreUserMap[it] = coreUserInfo }                    }                }.flatMap {                    loadCachedUserInfo(ListItems, userIdindex = List.userIdindex!!)                }.subscribe {                    subscriber.onNext(ListItems)                    subscriber.onCompleted()                }            }        }        return@flatMap Observable.just(ListItems)    }}fun loadCachedUserInfo(ListItems : List<ATListItem>, userIdindex : Int) : Observable<List<ATListItem>> {    return Observable.create<List<ATListItem>> { subscriber ->        ListItems.forEach { ListItem -> ListItem.coreUserInfo = coreUserMap[ListItem.valueForAttributeIndex(userIdindex)?.tolowerCase()] }        subscriber.onNext(ListItems)        subscriber.onCompleted()    }}fun fetchUserInfoForListItems(ListItems : List<ATListItem>, userIdindex: Int, force: Boolean) : Observable<List<CoreUserInfo>> {    val itemsToFetch = if ( force ) ListItems else ListItems.filter { it.coreUserInfo == null }    val IDs = itemsToFetch.map { it.valueForAttributeIndex(userIdindex) ?: "" }.filter { !it.isEmpty() }    val records = hashMapOf("records" to IDs)    if ( itemsToFetch.count() == 0 ) { return Observable.just(ArrayList<CoreUserInfo>()) }    return RuntimeDataController.dataService.fetchCoreUserInfo(recordsMap = records)            .map { Json ->                val userInfo = ArrayList<CoreUserInfo>()                Json.arrayValue("records").eachObject { userInfo.add(CoreUserInfo(it)) }                return@map userInfo            }}

解决方法:

Currently loadCachedUserInfo takes in an array of ListItem and returns that same array as an observable after the cached items have been associated with it. This feels wrong to me. I think instead this call should only return the items that have a cached UserInfo associated with it. However, I need to continue passing the full array of ListItem to the next method

我不确定我是否正确理解您,但是如果您只需要副作用(缓存),则可以使用doOnNext.例如,

.doOnNext { ListItems ->    if ( List.isUserList ) {        cache(ListItems, userIdindex = List.userIdindex!!)    }}fun cache(ListItems : List<ATListItem>, userIdindex : Int) {    // caching}
Do I need to do additional work to support unsubscribing?

不,AFAIK.

注意:

有关doOnNext的更多信息,请参见What is the purpose of doOnNext(…) in RxJava和here.

通常,如果lambda中的最后一条语句是表达式,则不需要return @….
例如.:

.flatMap { ListItems ->    if ( List.isUserList ) {        return@flatMap loadCachedUserInfo(ListItems, userIdindex = List.userIdindex!!)    }    return@flatMap Observable.just(ListItems)}    

可以这样写:

.flatMap { ListItems ->    if ( List.isUserList )        loadCachedUserInfo(ListItems, userIdindex = List.userIdindex!!)    else        Observable.just(ListItems)} 

我没有测试代码.

总结

以上是内存溢出为你收集整理的android-使用RxJava将本地数据与远程(或缓存)数据连接全部内容,希望文章能够帮你解决android-使用RxJava将本地数据与远程(或缓存)数据连接所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1120612.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-29
下一篇2022-05-29

发表评论

登录后才能评论

评论列表(0条)

    保存