web-dev-qa-db-fra.com

LiveData Observer non appelé

J'ai une activité, TabBarActivity qui héberge un fragment, EquipmentRecyclerViewFragment. Le fragment reçoit le rappel LiveData mais pas l'activité (comme vérifié avec des points d'arrêt en mode débogage). Ce qui est bizarre, c'est que le rappel d'activité se déclenche si j'appelle la méthode initData de ViewModel. Voici les sections pertinentes des composants mentionnés:

TabBarActivity

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    initVM()
    setContentView(R.layout.activity_nav)
    val equipmentRecyclerViewFragment = EquipmentRecyclerViewFragment()
    supportFragmentManager
            .beginTransaction()
            .replace(R.id.frameLayout, equipmentRecyclerViewFragment, equipmentRecyclerViewFragment.TAG)
            .commit()
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)

}

var eVM : EquipmentViewModel? = null
private fun initVM() {
    eVM = ViewModelProviders.of(this).get(EquipmentViewModel::class.Java)
    eVM?.let { lifecycle.addObserver(it) } //Add ViewModel as an observer of this fragment's lifecycle
    eVM?.equipment?.observe(this, loadingObserver)//        eVM?.initData() //TODO: Not calling this causes Activity to never receive the observed ∆
}
val loadingObserver = Observer<List<Gun>> { equipment ->
    ...}

EquipmentRecyclerViewFragment

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    columnCount = 2
    initVM()
}

//MARK: ViewModel Methods
var eVM : EquipmentViewModel? = null
private fun initVM() {
    eVM = ViewModelProviders.of(this).get(EquipmentViewModel::class.Java)
    eVM?.let { lifecycle.addObserver(it) } //Add ViewModel as an observer of this fragment's lifecycle
    eVM?.equipment?.observe(this, equipmentObserver)
    eVM?.initData()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(R.layout.fragment_equipment_list, container, false)
    if (view is RecyclerView) { // Set the adapter
        val context = view.getContext()
        view.layoutManager = GridLayoutManager(context, columnCount)
        view.adapter = adapter
    }
    return view
}

EquipmentViewModel

class EquipmentViewModel(application: Application) : AndroidViewModel(application), LifecycleObserver {
var equipment = MutableLiveData<List<Gun>>()
var isLoading = MutableLiveData<Boolean>()

fun initData() {
    isLoading.setValue(true)
    thread { Thread.sleep(5000) //Simulates async network call
        var gunList = ArrayList<Gun>()
        for (i in 0..100){
            gunList.add(Gun("Gun "+i.toString()))
        }
        equipment.postValue(gunList)
        isLoading.postValue(false)
    }
}

Le but ultime est que l'activité observe simplement le booléen isLoading MutableLiveData, mais comme cela ne fonctionnait pas, j'ai modifié l'activité pour observer uniquement l'équipement LiveData afin de minimiser le nombre de variables en jeu.

12
James Jordan Taylor

Pour obtenir la même référence de ViewModel que dans votre activité, vous devez passer la même activité, vous devez utiliser ViewModelProviders.of(getActivity), lorsque vous passez this vous recevez une nouvelle instance de ViewModel.

Pour plus d'informations Partager des données entre fragments

12
Pavel Poley