【问题标题】:How to perform call sequence to a REST API in Android App?如何在 Android 应用程序中执行对 REST API 的调用序列?
【发布时间】:2019-05-14 16:17:48
【问题描述】:

我很难调用我的 api。我将 Reactivex 与 kotlin 和 Flowables 一起使用。如果我通过“If-Modified_since”标头传递的日期小于上次更新,我的 API 会返回一个项目列表。 如果没有更新,我会作为应用返回 android 应用 304 错误。

我需要执行以下程序。 1->我调用api 2->如果调用成功,将列表保存在Realm中,返回viewmodel 3->如果错误是304,我对项目执行缓存搜索(领域) 4-> 如果是另一个错误,我会正常返回 ViewModel 的错误

这是下面的代码,但我不确定是不是这样。

override fun getTickets(eventId: String): Flowable<List<Ticket>> {
        return factory
                .retrieveRemoteDataStore()
                .getTickets(eventId)
                .map {
                    saveTickets(it)
                    it
                }.onErrorResumeNext { t: Throwable ->
                    if (t is HttpException && t.response().code() == 304) {
                        factory.retrieveCacheDataStore().getTickets(eventId)
                    } else
                        //Should return error
                }

问题是,最好的方法是什么?

谢谢。

【问题讨论】:

    标签: android kotlin rx-java reactivex


    【解决方案1】:

    我假设您正在使用 Retrofit。如果是这种情况,那么您可以将您的 getTickets 调用包含在 Single&lt;Response&lt;SomeModel&gt;&gt; 中。这样,在第一张地图上,您可以检查错误代码,其中包括:

    ...getTickets(id)
      .map{ response -> 
            when {
    response.isSuccessful && response.body!=null -> {
                                             saveTickets(it)
                                             it
    } 
    !response.isSuccessful && response.errorCode() == 304 -> {
    factory.retrieveCacheDataStore().getTickets(eventId)
    }
    else -> throw IOException()
    }
    }
    

    这当然可以使用标准/扩展函数做得很漂亮,但为了便于阅读,要保持简单。

    希望这会有所帮助!

    【讨论】:

    • 没错,我正在使用改造。我正在打电话并等待Flowable。 @GET("api/web/events/{event_id}/get-tickets") fun getTickets(@Header("If-Modified-Since") date: String, @Path("event_id") eventId: String): Flowable&lt;List&lt;Ticket&gt;&gt;
    【解决方案2】:

    我的大部分 cmets 都是我的解释。

    data class Ticket(val id:Int) { 
         companion object { 
             fun toListFrom(jsonObject: JSONObject): TICKETS { 
                 /**do your parsing of data transformation here */
                 return emptyList()
             }
         }
    }
    
    typealias TICKETS = List<Ticket>
    
    
    class ExampleViewModel(): ViewModel() {
    
        private var error: BehaviorSubject<Throwable> = BehaviorSubject.create()
        private var tickets: BehaviorSubject<TICKETS> = BehaviorSubject.create()
    
        /**public interfaces that your activity or fragment talk to*/
        fun error(): Observable<Throwable> = this.error 
        fun tickets(): Observable<TICKETS> = this.tickets
    
        fun start() {
    
            fetch("http://api.something.com/v1/tickets/")
                    .subscribeOn(Schedulers.io())
                    .onErrorResumeNext { t: Throwable -> 
                        if (t.message == "304") {
                            get(3)
                        } else {
                            this.error.onNext(t)
                            /** this makes the chain completed gracefuly without executing flatMap or any other operations*/
                            Observable.empty()
                        }
                    }
                    .flatMap(this::insertToRealm)
                    .subscribe(this.tickets)
    
        }
    
        private fun insertToRealm(tickets: TICKETS) : Observable<TICKETS> {
            /**any logic here is mainly to help you save into Realm**/
            /** I think realm has the option to ignore items that are already in the db*/
            return Observable.empty()
        }
    
        private fun get(id: Int): Observable<TICKETS> {
            /**any logic here is mainly to help you fetch from your cache**/
            return Observable.empty()
        }
    
        private fun fetch(apiRoute: String): Observable<TICKETS> {
            /**
             * boilerplate code 
               wether you're using Retrofit or Okhttp, that's the logic you 
               should try to have 
             * */
            val status: Int = 0
            val rawResponse = ""
            val error: Throwable? = null 
    
            val jsonResponse = JSONObject(rawResponse)
            return Observable.defer {
               if (status == 200) {
                   Observable.just(Ticket.toListFrom(jsonResponse))
               }
                else if (status == 304) {
                   Observable.error<TICKETS>(Throwable("304"))          
                }
                else {
                    Observable.error<TICKETS>(error)
                }
            }
        }
    
        override fun onCleared() {
            super.onCleared()
            this.error = BehaviorSubject.create()
            this.tickets = BehaviorSubject.create()
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-15
      • 2013-08-01
      • 2016-02-22
      • 2011-05-05
      • 1970-01-01
      • 2015-01-27
      • 2020-02-15
      • 1970-01-01
      相关资源
      最近更新 更多