Как наблюдать за данными из живых данных Android на трех разных фрагментах

У меня есть активность MainActivity.kt .

И и одна ViewModel MainActivityViewModel.kt

И я хочу наблюдать за своими живыми данными в трех разных фрагментах.

class MainActivity{
      
      lateinit var mainActivityViewModel: MainActivityViewModel
      ...

     mainActivityViewModel = ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java)
}

class MainFragmentOne{
      
      lateinit var mainActivityViewModel: MainActivityViewModel
      ...

     mainActivityViewModel = ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java)
}

Но мой наблюдатель работает только с активностью, а не с фрагментами.


person Hello world    schedule 28.08.2019    source источник


Ответы (4)


Эй, вы делаете все отлично, кроме одной вещи, которую вы должны использовать вместо этого requireActivity() в своем классе фрагментов.

Убедитесь, что весь ваш фрагмент прикреплен к вашей viewModel активности.

class MainActivity{

      lateinit var mainActivityViewModel: MainActivityViewModel
      ...

     mainActivityViewModel = ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java)
}

class MainFragmentOne{

      lateinit var mainActivityViewModel: MainActivityViewModel
      ...

     mainActivityViewModel = ViewModelProviders.of(requireActivity(), viewModelFactory).get(MainActivityViewModel::class.java)
}

Это поможет вам решить вашу проблему.

Подробнее см. здесь.

person Arbaz Pirwani    schedule 28.08.2019

ViewModelProviders.of имеет 2 разных конструктора:

of(Fragment fragment, ViewModelProvider.Factory factory)

Создает ViewModelProvider, который сохраняет ViewModels, пока область действия данного фрагмента жива.

of(FragmentActivity activity, ViewModelProvider.Factory factory)

Создает ViewModelProvider, который сохраняет ViewModels, пока активна область данного действия.

По сути, когда вы использовали this в качестве первого параметра в своей активности, вы передавали контекст активности и создавали модель представления, которая будет активна в рамках активности, однако ваш второй this< /strong> — это контекст вашего фрагмента, что означает, что вторая ViewModel будет жить, пока жив ваш фрагмент (только один фрагмент).

Что вместо этого вы должны делать в своем фрагменте, так это использовать контекст активности, поскольку активность всегда активна, когда фрагменты присоединяются и меняются местами. Вы должны изменить свои фрагменты на:

class MainFragmentOne{

      lateinit var mainActivityViewModel: MainActivityViewModel
      ...

     mainActivityViewModel = ViewModelProviders.of(activity!!, viewModelFactory).get(MainActivityViewModel::class.java)
}

или вы можете использовать метод requireActivity(), который был предыдущим ответом.

person Daniel    schedule 28.08.2019

Чтобы достичь того, что вы пытаетесь сделать, вам нужны три вещи. Действие/фрагмент, которое отправит значение в ViewModel, ViewModel, и действие/фрагмент, которое извлечет данные из ViewModel. Допустим, ваши данные хранятся в ArrayList, и вы хотите обновить и получить их из разных фрагментов.
Во-первых, мы должны реализовать ViewModel. Он содержит данные, которыми вы хотите поделиться между своими действиями/фрагментами. Вы объявляете MutableLiveData как ArrayList, а затем инициализируете его.

class testviewmodel : ViewModel() {
    val list: MutableLiveData<ArrayList<String>> = MutableLiveData()
    init {
        list.value = arrayListOf()
    }
}

Наш следующий шаг — получить доступ и обновить ArrayList, используя вашу активность:

    val viewmodel = ViewModelProviders.of(this).get(testviewmodel::class.java)
    // update the array in Viewmodel
    viewmodel.list.postValue(yourarray)

Если вы используете Fragment для его обновления, используйте это:

    activity?.let {
        val viewmodel = ViewModelProviders.of(it).get(testviewmodel::class.java)
         // update the array in Viewmodel
        viewmodel.list.postValue(yourarray)
    }

Наконец, чтобы получить данные из ViewModel во фрагменте, поместите это внутрь вашего onViewCreated:

activity?.let {
    val viewmodel = ViewModelProviders.of(it).get(Dbviewmodel::class.java)
    observeInput(viewmodel)
}

Поместите это вне вашего onViewCreated:

private fun observeInput(viewmodel: testviewmodel ) {

    viewmodel.list.observe(viewLifecycleOwner, Observer {
        it?.let {
            if (it.size > 5) {
                pos = it[5]
//grab it
                Toast.makeText(context,pos,Toast.LENGTH_LONG).show()
//display grabbed data
            }
        }
    })
}

Взгляните на эти документы для получения дополнительной информации о ViewModels
Удачи! ! Надеюсь, это поможет :)

person Uni    schedule 01.09.2019

Это потому, что вы используете экземпляр «этого» фрагмента, а не действие.

Заменять

mainActivityViewModel = ViewModelProviders.of(this, viewModelFactory).get(MainActivityViewModel::class.java)

С

activity?.let { mainActivityViewModel = ViewModelProviders.of(it, viewModelFactory).get(MainActivityViewModel::class.java) }
person Wahyu Anggara Raya    schedule 07.12.2019