Android Retrofit处理Token过期

介绍

在Android开发中,使用Retrofit进行网络请求是一个常见的做法。然而,当我们的应用需要进行用户身份验证并使用Token来保护接口时,我们需要特别处理Token过期的情况。本文将向刚入行的开发者介绍如何在Android中使用Retrofit处理Token过期的问题。

流程概述

下表展示了处理Token过期的整体流程:

步骤 动作 代码
1 发送网络请求 Retrofit的接口定义
2 检查响应 拦截器
3 判断Token是否过期 响应中的状态码或自定义字段
4 刷新Token 发送刷新Token的网络请求
5 更新Token 缓存或本地存储新的Token
6 重新发送原始请求 重新发起之前失败的请求

接下来,我们将详细讨论每个步骤需要做什么以及涉及的代码。

1. 发送网络请求

首先,我们需要使用Retrofit发送网络请求。这需要定义一个接口来描述我们的API,并使用Retrofit创建一个实例。以下是一个示例:

interface ApiService {
    @GET("/users/{user}")
    fun getUser(@Path("user") user: String): Call<User>
}

val retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val apiService = retrofit.create(ApiService::class.java)

2. 检查响应

为了处理Token过期,我们需要拦截每个请求的响应。我们可以使用Retrofit的拦截器来实现这一点。以下是一个示例:

class TokenInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val response = chain.proceed(request)
        
        // 处理响应
        
        return response
    }
}

// 在Retrofit中添加拦截器
val okHttpClient = OkHttpClient.Builder()
    .addInterceptor(TokenInterceptor())
    .build()

val retrofit = Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(okHttpClient)
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val apiService = retrofit.create(ApiService::class.java)

3. 判断Token是否过期

在处理响应之前,我们需要判断Token是否过期。这可以通过检查响应的状态码或自定义字段来完成。以下是一个示例:

class TokenInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val response = chain.proceed(request)
        
        if (response.code() == 401) {
            // Token过期,需要刷新Token
        }
        
        return response
    }
}

4. 刷新Token

如果Token过期,我们需要发送一个刷新Token的网络请求。这可以使用与之前相同的Retrofit实例和接口来完成。以下是一个示例:

class TokenInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val response = chain.proceed(request)
        
        if (response.code() == 401) {
            val refreshTokenResponse = apiService.refreshToken().execute()
            
            if (refreshTokenResponse.isSuccessful) {
                val newToken = refreshTokenResponse.body()?.token
                
                // 更新Token
            }
        }
        
        return response
    }
}

interface ApiService {
    @GET("/refresh_token")
    fun refreshToken(): Call<TokenResponse>
}

5. 更新Token

当我们成功刷新Token后,我们需要将新的Token保存起来以供后续使用。这可以使用SharedPreferences或其他本地存储机制来完成。以下是一个示例:

class TokenInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val response = chain.proceed(request)
        
        if (response.code() == 401) {
            val refreshTokenResponse = apiService.refreshToken().execute()
            
            if (refreshTokenResponse.isSuccessful) {
                val newToken = refreshTokenResponse.body()?.token
                
                // 更新Token
                saveToken(newToken)
                
                // 重新发送原始请求
                return chain.proceed(request)
            }
        }
        
        return response
    }
}

fun saveToken(token: String?) {
    // 保存Token到SharedPreferences或其他本地存储机制
}
``