Retrofit2應對各類奇葩接口的方法

最近這一年半,實在是大開眼界了,面對各類奇葩的接口,在緊湊的開發週期下,沒有時間細想如何去面對,好在最近稍微悠閒了,就把遇到的各類奇葩接口整理了一下,本身手寫Spring去模擬這些接口,而後嘗試用Retrofit一一破解,終於被我摸出了一些門道。java

Post請求上傳Json

首先說明一點,用Json作先後端交互實際上是很好的作法,我我的也很推薦這樣來玩。spring

遇到這種場景,咱們首先想到的就是百度,而後咱們會了解如下寫法:json

方法1:後端

@Headers("Content-Type: application/json;charset=UTF-8", "Accept: application/json")
@POST(ServerAPI.JPUSH_UPLOAD_DEVICE_TOKEN_INFO)

fun uploaddevicetoken(@Body body: RequestBody): Single<LaiKangJunVO<Any>>


//--------------------------
val gson = Gson()
val jsonJpushStr = gson.toJson(jpushload)
val requstBody = RequestBody.create(MediaType.parse("application/json"), jsonJpushStr)
val disposable = accountService.uploaddevicetoken(requstBody)
.subscribeOn(Schedulers.io())

這種方式並無錯,可是咱們忽略了一點,咱們添加了ConverterFactory。咱們都知道,若是添加ConverterFactory,就能夠直接這樣寫:app

方法2:ide

@POST("test4")
fun test4(@Body test: Test):Single<Bean>

//----------------------
service.test4(Test("XXX", 11))
	.subscribeOn(Schedulers.io())
	.subscribe({
	val i = 0
	}, {
	val i = 0
	})

直接把對象當參數傳入便可,是否是方便不少?ui

傳遞空Json

有個弟弟寫過一個接口,讓我傳一個空的Json串,即「{}」,我先用上面的方法1來跑,無論怎麼寫retrofit都會報錯,時間緊沒辦法,我跑去找弟弟吵了一架,讓人家改了。可是後來反思,當哥的應該儘可能兼容弟弟,這個問題該怎麼解決呢,之後再遇到這問題該怎麼處理,直到我用上面的方法2傳遞了一個空的對象,終於解決了:url

data class TestBean()

@POST("test4")
fun test(@Body bean: TestBean):Single<Bean>

//----------------------
service.test(TestBean())
	.subscribeOn(Schedulers.io())
	.subscribe({
	val i = 0
	}, {
	val i = 0
	})

接口只返回ResponseHeader

事情的原由是,在作「註銷」接口時,後端弟弟在spring攔截器裏面去攔截參數,不知足的話他不能返回responseBody,只能返回一個responseHeder,可是因爲咱們用了ConverterFactory,retrofit會自動把responseBody反序列化成對象,但此時的responseBody是個空串,因此在解析的時候就會報解析錯誤end of .....code

應對這種場景,咱們能夠直接使用retrofit內部的okhttp來實現:對象

private fun ok() {
	val req = Request.Builder()
	.url(url + "test")
	.build()

	val moshi = Moshi.Builder().build()
	val call = client.newCall(req)
	call.enqueue(object : Callback {
	override fun onResponse(call: Call, response: Response) {
	val head = response.headers()
	val head1 = response.header("Date")
	val test = TestJsonAdapter(moshi).fromJson(response.body()?.source())
	val i = 0

	}

	override fun onFailure(call: Call, e: IOException) {
	val i = 0
	}
	})
}

可是這樣以來就形成了咱們的代碼的不統一。在我百般嘗試和各類百度後,終於找到一篇帖子,因而有了如下的解決方案:

@POST("test4")
    fun test4(@Body test: Test):Single<retrofit2.Response<Boolean>>
	
//---------------------------------

private fun retrofit4():Disposable {
	return service.test4(Test("XXX", 11))
	.subscribeOn(Schedulers.io())
	.subscribe({
		val i = 0
		val token = it.headers()["token"]
	}, {
		val i = 0
	})
}

登陸後全局加參數/動態切換全局參數

咱們都知道retrofit能夠全局在請求頭中加參數:

val client = OkHttpClient.Builder()
client.addInterceptor {
	val oriReq = it.request()
	val req = oriReq.newBuilder()
	.header("token", token.toString())
	.method(oriReq.method(), oriReq.body())
	.build()
	it.proceed(req)
}
retrofit = Retrofit.Builder()
	.baseUrl(url)
	.client(client.build())
	.addConverterFactory(MoshiConverterFactory.create())
	.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
	.build()
service = retrofit.create(Service::class.java)
相關文章
相關標籤/搜索