【发布时间】:2022-09-29 02:58:53
【问题描述】:
在这个应用程序中,我使用了Blogger API,我有这个获取帖子的方法
@GET
suspend fun getPostList(@Url URL: String): Response<PostList>
这是我使用的基本 URL
const val BASE_URL = \"https://www.googleapis.com/blogger/v3/blogs/$BLOG_ID/posts/\"
当第一次请求时它变成这样
https://www.googleapis.com/blogger/v3/blogs/12345678910/posts/maxResults=20&key=API_KEY
当第二个请求它应该得到一个令牌参数pageToken=ABCDE 导致我需要进行分页,所以我编辑基本网址在 viewModel 中添加 pageToken 参数,然后我再次将它传递给 getPostList 方法
它看起来像这样
https://www.googleapis.com/blogger/v3/blogs/12345678910/posts/maxResults=20&pageToken=ABCDEFG&key=API_KEY
这是我的网络层
private val interceptor : HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
this.level = HttpLoggingInterceptor.Level.BODY
}
@Singleton
@Provides
fun postAPIService(): PostAPIService {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(
OkHttpClient.Builder().readTimeout(
15, TimeUnit.SECONDS
).connectTimeout(15, TimeUnit.SECONDS)
.addNetworkInterceptor(interceptor)
.addInterceptor { chain ->
val url = chain
.request()
.url
.newBuilder()
.addQueryParameter(\"maxResults\", Constants.MAX_RESULT)
.addQueryParameter(\"key\", Constants.API_KEY)
.build()
chain.proceed(chain.request().newBuilder().url(url)
.build())
}.build()
)
.addConverterFactory(GsonConverterFactory.create())
.build().create(PostAPIService::class.java)
}
}
在视图模型层:
/** RETROFIT **/
var postsResponse: MutableLiveData<NetworkResult<PostList>> = MutableLiveData()
var postListResponse: PostList? = null
val label = MutableLiveData<String>()
var finalURL: MutableLiveData<String> = MutableLiveData()
private val token = MutableLiveData<String?>()
private suspend fun getPostsSafeCall() {
postsResponse.postValue(NetworkResult.Loading())
Log.e(TAG, \"getPostsSafeCall finalURL is ${finalURL.value!!}\")
if (hasInternetConnection()) {
try {
if (finalURL.value.isNullOrEmpty()) {
finalURL.postValue(BASE_URL)
}
val response = mainRepository.remoteDataSource.getPostList(finalURL.value!!)
postsResponse.value = handlePostsResponse(response)
} catch (exception: Exception) {
postsResponse.postValue(NetworkResult.Error(exception.message.toString()))
// Log.e(TAG, e.message + e.cause)
if (exception is HttpException) {
errorCode.postValue(exception.code())
Log.e(TAG, \"getPostsSafeCall: errorCode $errorCode\")
Log.e(TAG, \"getPostsSafeCall: ${exception.message.toString()}\")
}
}
} else {
postsResponse.postValue(NetworkResult.Error(\"No Internet Connection.\"))
}
}
private fun handlePostsResponse(response: Response<PostList>): NetworkResult<PostList> {
if (response.isSuccessful) {
token.value = response.body()?.nextPageToken
Log.d(TAG, \"handlePostsResponse: token = ${response.body()?.nextPageToken.toString()}\")
response.body()?.let { resultResponse ->
Log.d(
TAG, \"handlePostsResponse: old token is: ${token.value} \" +
\"new token is: ${resultResponse.nextPageToken}\"
)
finalURL.postValue(
BASE_URL + \"&pageToken=${token.value}\"
)
if (postListResponse == null) {
postListResponse = resultResponse
} else {
val oldPosts = postListResponse?.items
val newPosts = resultResponse.items
oldPosts?.addAll(newPosts)
}
Log.d(TAG, \"handlePostsResponse: ${token.value}\")
Log.e(TAG, \"handlePostsResponse finalURL is ${finalURL.value!!}\")
for (item in resultResponse.items) {
insertItem(item)
}
return NetworkResult.Success(postListResponse ?: resultResponse)
}
} else {
if (token.value == null) {
errorCode.postValue(400)
} else {
errorCode.postValue(response.code())
}
Log.d(TAG, \"handlePostsResponse: ${response.code().toString()}\")
Log.d(TAG, \"handlePostsResponse: ${response.headers().toString()}\")
Log.d(TAG, \"handlePostsResponse: ${response.headers().toString()}\")
// Log.d(TAG, \"handlePostsResponse: final ${finalURL.value.toString()}\")
return NetworkResult.Error(
\"network results of handlePostsResponse ${response.body().toString()}\"
)
}
return NetworkResult.Error(
\"network results of handlePostsResponse ${response.body().toString()}\"
)
}
我需要的
一种注入pageToken参数的方法动态的只有当有一个值(NOT NULL OR EMPTY)来避免最终/基本 URL 中的以下内容时
https://www.googleapis.com/blogger/v3/blogs/4294497614198718393/posts/?maxResults=20&pageToken=null&key=API_KEY
这会导致错误 400 badRequest
{
\"error\": {
\"code\": 400,
\"message\": \"We\'re sorry, but the value for field pageToken was not valid.\",
\"errors\": [
{
\"message\": \"We\'re sorry, but the value for field pageToken was not valid.\",
\"domain\": \"global\",
\"reason\": \"invalid\"
}
]
}
}
我尝试编辑 PostAPIService 方法使其看起来像这样
@GET(\"posts\")
suspend fun getPostList(@Query(\"pageToken\") pageToken: String=\"\"): Response<PostList>
并像这样在viewModel中使用它
val response = if (token.value.isNullOrEmpty()) {
mainRepository.remoteDataSource.getPostList()
} else {
mainRepository.remoteDataSource.getPostList(token.value!!)
}
但不幸的是,这也会导致 badRequest 也是因为pageToken=null inBASE_URL
标签: android kotlin retrofit retrofit2 okhttp