Я никогда не захожу внутрь LiveDataScope внутри моей модели представления - PullRequest
2 голосов
/ 30 января 2020

Я разработал 2 функции для входа в систему.

Первый « loginOne » работает, когда я использую область видимости модели.

Другой не работает, когда я использую область LiveData.

У вас есть идея? Я хочу, чтобы " loginTwo " работал.

API

interface LoginAPI {

    @POST("login")
    suspend fun getUser(@Body loginRequest: LoginRequest): User
}

Репозиторий

class LoginRepository(private val loginAPI: LoginAPI) {

    suspend fun getUser(loginRequest: LoginRequest) = loginAPI.getUser(loginRequest)
}

ViewModel

class LoginViewModel(private val loginRepository: LoginRepository) : ViewModel() {

    private var user: LiveData<User>? = null

    fun loginOne(username: String, password: String) {
        viewModelScope.launch {
            // i can enter here and get the user :)
            val user = loginRepository.getUser(LoginRequest(username, password))
            user
        }
    }

    fun loginTwo(username: String, password: String) {
        user = liveData(Dispatchers.IO) {
            // i never enter inside.. why ?
            val user = loginRepository.getUser(LoginRequest(username, password))
            emit(user)
        }
    }

    fun getUser(): LiveData<User>? = user
}

Фрагмент , моя viewModel вводится с Коин

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
   super.onViewCreated(view, savedInstanceState)

   loginViewModel.getUser()?.observe(this, Observer { user ->
       Log.d(LoginFragment::class.java.name, "User : $user ")
   })

   loginViewModel.loginOne("user","pcw123")
   loginViewModel.loginTwo("user","pcw123")
}

Ответы [ 2 ]

2 голосов
/ 30 января 2020

Убедитесь, что вы правильно создали Scope. Кроме того, вы используете соответствующий Dispatchers для достижения желаемых результатов.

Вы можете дополнительно проверить, выполняется ли вызов, когда вы хотите postValue. Проверьте, если Job еще жив.

Проверьте это вещь . Ваш вызов emmit выглядит подозрительно.

При использовании LiveData может потребоваться асинхронный расчет значений. Например, вы можете получить пользовательские настройки и передать их в свой пользовательский интерфейс. В этих случаях вы можете использовать функцию построителя liveData для вызова функции приостановки, передавая результат в качестве объекта LiveData.

Каждый вызов emit () приостанавливает выполнение блока до тех пор, пока значение LiveData не будет установлено на основной поток.

В приведенном ниже примере loadUser () является функцией приостановки, объявленной в другом месте. Используйте функцию построителя liveData для асинхронного вызова loadUser (), а затем используйте emit () для выдачи результата:

val user: LiveData<User> = liveData {
    val data = database.loadUser() // loadUser is a suspend function.
    emit(data)
}

РЕДАКТИРОВАТЬ: MutableLiveData для user переменная - решает проблему.

1 голос
/ 30 января 2020

Из документации:

Строительный блок liveData служит структурированным примитивом параллелизма между сопрограммами и LiveData. Блок кода начинает выполняться, когда LiveData становится активным , и автоматически отменяется после настраиваемого тайм-аута, когда LiveData становится неактивным.

Таким образом, в вашем случае «пользовательские» liveData уже активирован, когда вы наблюдаете это от фрагмента. Поскольку вы вызвали loginTwo () после наблюдения liveData, функция emit больше не будет срабатывать. Попробуйте вызвать loginTwo () перед наблюдением liveData, чтобы получить значение emit из liveData ktx.

...