ViewModel如何观察列表?MediatorLiveData onChange从未被调用



我想启动一个CoroutineScope,以便在闪屏期间开始从数据库加载数据,以便主活动可以快速显示数据,但我不想延迟闪屏以等待结果(这是一个很好的实践?)

当Main活动用ViewModel列表的观察者设置UI时,调用ViewModelloadList(),这样它就可以获得由Repository加载的列表并发布值,这样观察者就会被触发。但是存储库工作在不同的线程上,ViewModel可以首先请求存储库填充的数据。因此,当存储库从数据库加载数据时,我需要触发ViewModel

SplashScreen的代码:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//this class load the data from database
PersistenceSingleton.getInstance(application)
startActivity(Intent(this, MainActivity::class.java))
finish()
}

PersistenceSingleton:

private var dbAccess: PersistenceSingletonRepository? = null // Singleton
private lateinit var db: PokemonDatabase
var listOfPokemon: MutableLiveData<MutableList<Pokemon>> = MutableLiveData()
fun getInstance(context: Context) = synchronized(this){
if (dbAccess == null) {
dbAccess = PersistenceSingleton()
db = PokemonDatabase.getInstance(context)
//load all pokemon
CoroutineScope(Dispatchers.IO).launch {
val lan = Locale.getDefault().language
val list = if (lan.equals("it")) {
db.pokemonDao().loadAllPokemonIt()
} else {
db.pokemonDao().loadAllPokemon()
}
CoroutineScope(Dispatchers.Main).launch {
listOfPokemon.value = list
}
}
}
dbAccess
}

ViewModel:

var pokemonList: MutableLiveData<MutableList<Pokemon>> = MutableLiveData()
fun loadLists() {
//list could be empty. ViewModel need to observe the list on PersistenceSingleton (Repository)
pokemonList.value = PersistenceSingleton.listOfPokemon.value
}

主活动setUI:

private fun setUI() {
val observer = Observer<List<Pokemon>> { list ->
if (list != null) {
//hide progress bar  and set recycler view adapter
binding.pbPokemonlist.visibility = View.INVISIBLE
adapter = PokemonListAdapter(list)
binding.rvPokemon.adapter = adapter
}
}
pokemonListVM.pokemonList.observe(this, observer)
//inflate the recycler view
pokemonListVM.loadLists()
}

编辑

使ViewModel成为一个观察者,我使用MediatorLiveData,所以我的新ViewModel:

var pokemonList: MutableLiveData<MutableList<Pokemon>> = MutableLiveData()
private val pokemonListMediator: MediatorLiveData<List<Pokemon>> = MediatorLiveData()
init {
val observer = Observer<MutableList<Pokemon>> { list ->
Log.d("POKEMON", "onChange")
pokemonList.value = list
}
pokemonListMediator.addSource(PersistenceSingletonRepository.listOfPokemon, observer)
}
//load full list of Pokemon
fun loadLists() {
//list could be empty. ViewModel need to observe the list on PersistenceSingleton (Repository)
pokemonList.value = PersistenceSingletonRepository.listOfPokemon.value
}

但是观察者onChange()从未被调用过

您可以将Lists置于ViewModel中并使它们成为MutableLiveData

您将开始在ActivityonCreate函数内observeMutableLiveData对象。

在完成了最低限度的设置之后,在onCreate中调用loadLists。(就像获得RecyclerView并设置其Adapter,以便您的数据有地方去)

你的loadList函数应该看起来像这样

public var pokemonList: MutableLiveData<List<Pokemon>> = MutableLiveData()
public var typeList : MutableLiveData<List<Type>> = MutableLiveData() 
fun loadLists(context: Context) {
db = PokemonDatabase.getInstance(context)
//separate CoroutineScope for each database call
CoroutineScope(Dispatchers.IO).launch {
pokemonList.postValue(db.pokemonDao().loadAllPokemon())
}
CoroutineScope(Dispatchers.IO.launch{
typeList.postValue(db.pokemonDao().loadAllType())
}
}

你的OnCreate应该有这个

mainViewModel.pokemonList.observe(this, Observer { pokemans ->
//something like this
pokemonAdapter.list = pokemans
})
mainViewModel.typeList.observe(this, Observer { types->
//something like this
typeAdapter.list = types
})

这样,你的数据应该很快就能得到,任何更复杂的东西都会伤害到你。

编辑:配合你的编辑。

差不多了,你只需要另一个回调,我将使用

androidx.lifecycle.Observer<T>

PersistenceSingleton.getInstance(getApplication())!!.getListOfPokemon(
Observer<List<Pokemon>> { pokemon ->{
pokemonList.postValue(pokemon)
}
)

然后在getListOfPokemon函数

CoroutineScope(Dispatchers.IO).launch {
observer.onChanged(db.pokemonDao().loadAllPokemon())
}

当且仅当pokemon可用时,这将返回pokemon列表。你不必担心口袋妖怪的空列表,因为在有实际数据之前不会发出任何东西。

相关内容

  • 没有找到相关文章

最新更新