【问题标题】:android connecting restful api with mvvm patternandroid将restful api与mvvm模式连接起来
【发布时间】:2021-06-11 19:54:04
【问题描述】:

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

所以当我想调用一个 api 时,我在 Repository 中调用它,它是一个 kotlin 对象,这样它就变成了单例。 在这个应用程序中,当我调用 api 时,我应该添加一个授权标头,从SharedPreferences 获取令牌并分配给此标头。

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 类仅在应用程序启动后才被初始化,它不会从SharedPreferences 获得新令牌。我的意思是改造实例只构建一次。

那么我该如何解决这个问题呢?我应该为每个 api 调用动态添加标题吗? (有很多调用需要授权标头,这就是为什么我没有在每个请求中添加标头,而是添加了interceptor

【问题讨论】:

    标签: android kotlin retrofit okhttp android-mvvm


    【解决方案1】:

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

    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
    }
    

    【讨论】:

    • 但这是一回事。改造实例只构建一次,所以我们构建 OkHttpClient 时会使用令牌,我的意思是以后不会再调用它,我错了吗?
    • 每次调用这个改造变量时,都会使用Authorization Header调用一个API。
    • 是的,但我也做了同样的事情,有什么区别?
    • 在您的示例中,令牌在启动时被读取一次,而在第二次中,它在每个 http 调用的拦截器调用时被调用。
    猜你喜欢
    • 2012-05-15
    • 2013-09-26
    • 1970-01-01
    • 2012-04-05
    • 2017-03-07
    • 2017-08-08
    • 2015-09-10
    • 2011-10-17
    • 1970-01-01
    相关资源
    最近更新 更多