Как прочитать ответ на изменение в шаблоне репозитория с помощью сопрограмм

#android #mvvm #retrofit #repository-pattern #kotlin-coroutines

Вопрос:

В настоящее время я следую учебнику по архитектуре MVVM и репозитория в Android, и из-за абстракций в учебных кодах, с которыми я столкнулся, есть некоторые вещи, которые я не понимаю.

Хотя код работает нормально (компилируется без каких-либо проблем), абстракция затрудняет мне понимание того, как обрабатывать модифицированные ответы.

Хранилище

 suspend fun login(username: String, password: String) { // LiveData<List<AuthModel>> {
    withContext(Dispatchers.IO) {
        val auth = Network.retrofitInstance?.create(AuthService::class.java)
        val i = auth?.doLoginAsync(username, password)?.await()
        if (i != null) {
            database.authDao.updateAuthInfo(*i.asDatabaseModel())
        }
    }
    //return auth
  }
} 
 

Интерфейс

 interface ServiceSectionDao{
  @POST("login")
  fun doLoginAsync(
    @Query("user_id") userName: String,
    @Query("password") passWord: String
  ): Deferred<NetworkAuthContainer>
}
 

Объект Модернизации

 object Network {

 private var retrofit: Retrofit? = null
 private val BASE_URL = "http://10.0.2.2:8081/api/"

 val retrofitInstance: Retrofit?

 get() {
        if (retrofit == null) {
            var client = OkHttpClient.Builder()
                .addInterceptor(RequestInterceptor())
                .build()

            retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .build()

        }
        return retrofit
    }
 

Перехватчик Запросов

 class RequestInterceptor : Interceptor {
 var token = "FmQ54sSLm0H0P83EFU7fB2k9flgs5fXQNBS7EgtH";

   fun Token(token: String) {
     this.token = token;
   }

 override fun intercept(chain: Interceptor.Chain): Response {
    var request = chain.request()

    if (request.header("No-Authentication") == null) {
        //val token = getTokenFromSharedPreference();
        //or use Token Function
        if (!token.isNullOrEmpty()) {
            val finalToken = "Bearer "   token
            request = request.newBuilder()
                .addHeader("Authorization", finalToken)
                .build()
        }
     }
     return chain.proceed(request)
  }
}
 

Что я получаю сверху val i = auth?.doLoginAsync(имя пользователя, пароль)?.await() уже является NetworkAuthContainer, у меня нет возможности проверить наличие какого-либо кода состояния HTTP.

Во время отладки я могу видеть объект результата, возвращенный при обновлении, но я не могу его обработать, потому что я не знаю, где в коде я должен прочитать значения, которые должны быть в RequestInterceptor или репозитории(логин) и как?

Ответ №1:

Первая проблема с вашим кодом заключается в том, что вы используете устаревшую программу CoroutineCallAdapterFactory, начиная с версии 2.6. При обновлении теперь есть встроенная поддержка функций приостановки kotlin. поэтому первое, что вам следует сделать, это обновить свою Retrofit учетную запись до последней версии.

Как только вы это сделаете, вы сможете обновить свой doLoginAsync

 @POST("login")
suspend fun doLogin(                    // use of suspend modifier
    @Query("user_id")  userName: String,
    @Query("password") passWord: String): NetworkAuthContainer     // no need to use Deffered
 

Теперь, чтобы получить HTTP код состояния из ответа, вы можете обновить тип возврата doLogin в retrofit2.Response<NetworkAuthContainer> и в своем репозитории

  val response = auth!!.doLoginAsync(username, password)    // This is HTTP response
 if (response.code() == 200) {
     // To get NetworkAuthContainer call body()
     database.authDao.updateAuthInfo(*response.body().asDatabaseModel())  
 }
 else{
      // Handle different response codes
 }