android 使用 mvvm 模式连接 restful api

android connecting restful api with mvvm pattern

我正在使用我的自定义后端实现用户登录和注册,在其中我在注册时获得一个令牌,或者 login.Then 我将该令牌保存在 SharedPreferences.

所以当我想调用一个 api 时,我在 Repository 中调用它,它是一个 kotlin object 这样它就变成了单例。 在这个应用程序中,当我调用 api 时,我应该添加一个 授权 header,从 [=14= 获取令牌] 并分配给这个 header.

object MainRepository {
    private var sharedPreferencesRepository: SharedPreferencesRepository
    private var retrofit: Retrofit
    private lateinit var mainApi:MainApi

  init {
    sharedPreferencesRepository = SharedPreferencesRepository(MyApplication.context)
    val user = sharedPreferencesRepository.getUser()
    
    val httpClient = OkHttpClient.Builder()
        .addInterceptor(MyOkHttpClientInterceptor(user.token))
        .build()
    retrofit =
        Retrofit.Builder().baseUrl(API_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient)
            .build()
        mainApi = retrofit.create(MainApi::class.java)
    }
  fun getSomethingFromApi() = myApi.getSomething()
}

问题是,当我启动应用程序并登录时,它工作正常。但是当我注销并再次登录时,因为 MainRepository class 仅在应用程序启动后才初始化,所以它不会从 SharedPreferences 获取新令牌。我的意思是改造实例只构建一次。

那么我该如何解决这个问题呢?我应该为每个 api 调用动态添加 header 吗? (有这么多调用需要授权header,所以我没有在每次请求时添加header ,相反,我添加了一个 interceptor)

您可以添加拦截器并在OkhttpClient.Builder()中添加您的授权header。

class RetrofitPrivateService {
    var token = SharedPreferencesHelper().getToken()

    companion object {
        private val interceptor: HttpLoggingInterceptor = HttpLoggingInterceptor(ApiLogger())
                .setLevel(HttpLoggingInterceptor.Level.BODY)

        private val client = OkHttpClient.Builder()
                .readTimeout(60, TimeUnit.SECONDS)
                .connectTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .addInterceptor(object : Interceptor {
                    override fun intercept(chain: Interceptor.Chain): Response {
                        val request = chain.request().newBuilder()
                                .addHeader("Authorization", "Bearer " + RetrofitPrivateService().token)
                                .build()
                        return chain.proceed(request)
                    }
                })
                .addInterceptor(interceptor)
                .build()

        private val retrofit = Retrofit.Builder()
                .baseUrl(API_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build()

        // function to access your API here
}