Kotlin - 在 运行 函数之前等待多个 LiveData 被观察

Kotlin - wait for multiple LiveData to be observe before running function

我正在使用 viewModel 从房间数据库中提取实时数据。我有 2 个从我的 viewModel 中提取的 LiveData,然后我将 运行 一个函数从我的服务器中提取数据。我需要在 运行 设置将从我的服务器获取信息的函数之前设置这两个值,因为这些值是 post.

正文的一部分

这是我的一部分 activity

var locationSeleted:Long=0L

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView<ActivityBinding>(this,R.layout.activity)

        //This is to get the viewmodel
        val application = requireNotNull(this).application
        val dataSource = Database.getInstance(application).DatabaseDao
        val viewModelFactory = ViewModelFactory(dataSource, application)
        val ViewModel = ViewModelProviders.of(this,viewModelFactory).get(ViewModel::class.java)

        binding.ViewModel = ViewModel
        binding.setLifecycleOwner (this)

        //Get location from livedata
        ViewModel.Location.observe(this, Observer {location ->

            if (location == null){
                //do something
            }
            else{
                locationSeleted = location.locationId
            }

        })

        //listens to the live data of the products value
        ViewModel.Products.observe(this, Observer{products ->
            
            if (products == null){
                //do something
            }
            else{
                myfunction(products)
            }

        })

这是我的视图模型的一部分

class ViewModel(val database: DatabaseDao, application: Application) : AndroidViewModel(application) {


    //This gets the location selected
    var Location: LiveData<LocationSelect> = database.get_location()

    //This line gets the products
    var Products: LiveData<Array<Products>> = database.get_products()


我当前的代码有效,但我可以想象,如果 Location LiveData 被延迟,那么我的函数将 运行 没有位置,并且 Post 调用将为 false。我的问题是当从 viewModel 设置位置和产品时如何调用 myfunction?还是有更好的方法。

谢谢你

您可以通过实时数据进行观察。在您的视图模型中:

val _weHaveAllTheData = MutableLiveData(pairToShowSpinner)
val weHaveAllTheData: LiveData<Pair<Boolean, Boolean>> = _weHaveAllTheData

fun updateTheData(int firstOrSecond: Int) { 
    val pair = _weHaveAllTheData.value
    if (firstOrSecond = 1) {
       
       val secondPair = pair?.second as Boolean
       val pairInObservable = Pair(true, secondPair)
       _weHaveAllTheData.value = pairInObservable
    } else {
       val firstPair = pair?.first as Boolean
       val pairInObservable = Pair(firstPair, true)
       _weHaveAllTheData.value = pairInObservable 
    }

}

在你的activity中:

    //Get location from livedata
    ViewModel.Location.observe(this, Observer {location ->

        if (location == null){
            //do something
        }
        else{
            locationSeleted = location.locationId
        }
        ViewModel.updateTheData(1)


    })

//listens to the live data of the products value
    ViewModel.Products.observe(this, Observer{products ->
        
        if (products == null){
            //do something
        }
        else{
            ViewModel.updateTheData(2)
            
        }

    })

    ViewModel.weHaveAllTheData.observe(lifecycleOwner, Observer {
        val positivePair = Pair(first = true, second = true)
        if (it == positivePair)
            myfunction(ViewModel.Products)
    })

您可以使用 MediatorLiveData,这样您只需观察一件事,它只会在收到两个项目时触发,并在之后的每次更改时触发。

在视图模型中:

val locationAndProductsLiveData: LiveData<Pair<LocationSelect, Array<Products>>> = 
    object: MediatorLiveData<Pair<LocationSelect, Array<Products>>>() {
        var location: LocationSelect? = null
        var products: Array<Products>? = null
        init {
            addSource(Location) { location ->
                this.location = location 
                products?.let { value = location to it }
            }
            addSource(Products) { products ->
                this.products = products 
                location?.let { value = it to products }
            }
        }
    }

在你的Activity中:

ViewModel.locationAndProductsLiveData.observe(this) { (location, products) ->
    locationSelected = location.Id
    myFunction(products)
}