我对科特林和观察员是陌生的。我正在使用Retrofit进行API调用。我的API调用以空数组形式返回响应。我无法弄清楚如何使用观察者来处理它。拜托,任何人,请帮帮我。预先感谢
API调用方法:
@GET("transaction/get")
fun getTransactions(@Query("date") date: String?, @Query("user_id") user_id: Int, @Query("account_id") account_id: Int?): Observable<TransactionModel>
连接类
public class ApiServiceNetwork private constructor()//hide the public constructor
: Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val builder: Request.Builder
builder = request.newBuilder()
val request1 = builder.build()
//Here we can modify request1 and response if we want (like adding header or auth)
val response = chain.proceed(request1)
return response
}
private val logger: okhttp3.logging.HttpLoggingInterceptor
get() {
val logging = okhttp3.logging.HttpLoggingInterceptor()
logging.level = okhttp3.logging.HttpLoggingInterceptor.Level.HEADERS
logging.level = okhttp3.logging.HttpLoggingInterceptor.Level.BASIC
logging.level = okhttp3.logging.HttpLoggingInterceptor.Level.BODY
return logging
}
fun getNetworkService(): WebServiceInterface {
return createRetrofitInstance(EndPoint.SERVER_ENDPOINT).create(WebServiceInterface::class.java)
}
private fun createRetrofitInstance(url: String): Retrofit {
val okHttpClient = OkHttpClient.Builder()
okHttpClient.addInterceptor(this)
okHttpClient.addNetworkInterceptor(StethoInterceptor())
okHttpClient.addInterceptor(logger)
retrofit.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create(GsonBuilder().serializeNulls().setLenient().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient.connectTimeout(60,
TimeUnit.SECONDS).writeTimeout(60,
TimeUnit.SECONDS).readTimeout(60,
TimeUnit.SECONDS).build())
return retrofit.build()
}
companion object {
private val retrofit = Retrofit.Builder()
fun getInstance(): ApiServiceNetwork {
return ApiServiceNetwork()
}
}
我的活动中的函数调用:
mApiServiceNetwork.getNetworkService().getTransactions(date, user_id, account_id)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
this.transaction = it
this.expenseDataAdapter.setExpenses(it.expenses!!)
this.recyclerView.adapter = expenseDataAdapter
this.textViewSpendingAccount.text = it.account!!.title
this.textViewSpendingExpense.text = it.total_expense.toString()
this.textViewSpendingIncome.text = it.total_income.toString()
this.textViewSpendingBalance.text = it.balance.toString()
Log.d("__EXPENSE", it.total_expense.toString())
}, {
Toast.makeText(this.requireContext(), it.message, Toast.LENGTH_LONG).show()
}, {
this.expenseDataAdapter.notifyDataSetChanged()
})
答案 0 :(得分:0)
如果您从不关心响应中的数据(即,如果它始终是一个空数组),则可以使用Completable
而不是Observable<TransactionModel>
。查看您的代码,情况似乎并非如此。
如果响应有时包含数据,有时返回空数组,则可以使用自定义Converter.Factory
截获GSON转换器工厂之前的调用,并以所需的方式格式化返回值。这将空响应限制为您可以接受的呼叫。
带有伪代码的示例:
class EmptyArrayConverterFactory : Converter.Factory() {
override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
val delegate = retrofit.nextResponseBodyConverter<Any>(this, type, annotations)
return Converter<ResponseBody, Any> { body ->
var bodyString = body.String()
if (bodyString == "{[]}") { // Or whatever the empty array is returned as
bodyString = //Convert body string to empty/error TransactionModel JSON
}
delegate.convert(bodyString)
}
}
}
Observable<ResponseBody>
而不是Observable<TransactionModel>
,然后在subscribe()
函数中自行解析响应,同时考虑到空数组的可能性。考虑到情况和我对您情况的有限了解,我认为这将是最灵活的选择。这看起来像这样:
API定义: @GET(“交易/获取”) fun getTransactions(@Query(“ date”)date:字符串?,@Query(“ user_id”)user_id:Int,@Query(“ account_id”)account_id:Int?):可观察
用法:
mApiServiceNetwork.getNetworkService().getTransactions(date, user_id, account_id)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ responseBody ->
if(responseBody.string() == "{[]}"){
// handle the empty list however you want
}
else{
// Handle the response normally
this.transaction = it
this.expenseDataAdapter.setExpenses(it.expenses!!)
this.recyclerView.adapter = expenseDataAdapter
this.textViewSpendingAccount.text = it.account!!.title
this.textViewSpendingExpense.text = it.total_expense.toString()
this.textViewSpendingIncome.text = it.total_income.toString()
this.textViewSpendingBalance.text = it.balance.toString()
Log.d("__EXPENSE", it.total_expense.toString())
}
}, {
Toast.makeText(this.requireContext(), it.message, Toast.LENGTH_LONG).show()
}, {
this.expenseDataAdapter.notifyDataSetChanged()
})