Инициализировать LiveData позже в ViewModel - PullRequest
0 голосов
/ 28 мая 2020

Недавно решив использовать LiveData, я столкнулся с проблемой при инициализации переменной. У меня есть 2 действия (я не использую навигацию, но дело не в этом):

  • Один - это список с элементами, получаемыми API
  • Другой - подробное действие для выбранный элемент в предыдущем списке

Проблема в том, что мне нужно иметь возможность обращаться к подробному действию в режиме создания, т.е. в моей ViewModel объект не должен быть получен через Retrofit, а создан через новый создание.

Вот как это делается сейчас:

Подробная активность:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.details)

        val isNew = intent.extras?.getBoolean("new")
        if (isNew) {
            // Trigger lazy property
            viewModel.value
        } else {
            viewModel.getDetails()
        }

        presenter.value.observe(this, Observer { value ->
            value?.let {
                displayDetails(it)
            }
        })
    }

ViewModel

class DetailsPresenter(private val repository: WorkOrderRepository)
    : ViewModel(), LifecycleObserver {

    val value: MutableLiveData<Details> by lazy { MutableLiveData(Details("")) }

    fun getDetails() {
        RetrofitClient.getDetails()
        .onSuccess {
            this.value.value = it
        }

    }

}

Проблема с этим методом в том, что мой метод displayDetails () вызывается дважды. Один для отложенной инициализации, а другой - на случай, если я просматриваю существующий элемент.

Как я могу инициализировать LiveData позже в коде?

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Конечно, он будет вызываться два раза, первый раз вызывается, потому что вы регистрируете наблюдателя в своем представлении, что заставляет lazy работать и создавать объект LiveData. Во второй раз он вызывается, потому что Retrofit обновляет объект LiveData. Вы делаете сетевой запрос, они всегда требуют времени для завершения, до тех пор ваша программа начинает выполнение следующей строки (в вашем случае она настраивает наблюдателя), ожидая завершения запроса.

Нет смысла лениво инициализировать объект value, если вы собираетесь наблюдать его независимо от условия if-else.

Я бы сделал вызов модернизации в init блок ViewModel и кэшируйте его там.

Вы можете использовать ключевое слово lateinit для последующей инициализации объекта.

lateinit var myLiveData: LiveData<T>

Чтобы проверить, инициализирован ли myLiveData, просто напишите if (::myLiveData.isInitialized)

0 голосов
/ 01 июня 2020

Обычно ленивый не создает второй экземпляр, ссылка ViewModel не воссоздается Таким образом, мы можем использовать значение Val: LiveData = MutableLiveData () вместо lazy

Вы можете добавить метод getDetails () в init заблокировать себя, чтобы избежать второго вызова

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...