未触发 LiveData 转换

LiveData Transformation not getting triggered

我在 ui 中订阅了 idssearch,但我没有得到任何结果,所以我逐步使用调试器,发现转换没有得到第一次后触发。因此,当我第一次调用 setIds 时,ids 得到更新,但对于第一次调用之后的每次调用,转换都不会触发。 search.

也是如此

有什么可能出错的想法吗?

class MyViewModel : ViewModel() {

    private val repository = Repository.sharedInstance

    var recentRadius: LiveData<List<RecentRadius>>?
    var recentRoute: LiveData<List<RecentRoute>>?

    init {
        recentRadius = repository.recentRadius()
        recentRoute = repository.recentRoute()
    }


    private val idsInput = MutableLiveData<String>()
    fun setIdsInput(textId: String) {
        idsInput.value = textId
    }

    val ids: LiveData<List<String>> = Transformations.switchMap(idsInput) { id ->
        repository.ids(id)
    }

    private val searchInput = MutableLiveData<Search>()
    fun setSearchInput(search: Search) {
        searchInput.value = search
    }


    val search: LiveData<SearchResult> = Transformations.switchMap(searchInput) { search ->
        when (search.type) {
            SearchType.ID -> repository.id(search)
            SearchType.RADIUS -> repository.radius(search)
            SearchType.ROUTE -> repository.route(search)
        }
    }
}

转换未被触发的最常见原因是没有 Observer 观察它或输入 LiveData 没有改变。

下面的示例说明了在 activity 中附加观察者时地图的使用。

Activity

class MainActivity : AppCompatActivity() {

lateinit var mBinding : ActivityMainBinding

private val mViewModel : MainViewModel by lazy {
   getViewModel { MainViewModel(this.application) }
}

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
   mBinding.vm = mViewModel

   // adding obeserver
   mViewModel.videoName.observe(this, Observer<String> { value ->
       value?.let {
           //Toast.makeText(this, it, Toast.LENGTH_LONG).show()
       }
   })
 }
}

ViewModel 与地图

class MainViewModel(val appContext : Application) : AndroidViewModel(appContext) {

   private val TAG = "MainViewModel"

   var videoData = MutableLiveData<VideoDownload>()
   var videoName : LiveData<String>

   init {
      // Update the data
      videoName = Transformations.map(videoData) { "updated : "+it.webUrl }
    }

    fun onActionClick(v : View) {
       // change data
       videoData.value = VideoDownload(System.currentTimeMillis().toString())
    }

    fun onReActionClick(v : View) {
       // check data
       Toast.makeText(appContext, videoName.value, Toast.LENGTH_LONG).show()
    }

}

ViewModel 与 switchMap

class MainViewModel(val appContext : Application) : AndroidViewModel(appContext) {

    private val TAG = "MainViewModel"

    var videoData = MutableLiveData<VideoDownload>()
    var videoName : LiveData<String>

    init {
       // Update the data
       videoName = Transformations.switchMap(videoData) { modData(it.webUrl) }

    }

    private fun modData(str: String): LiveData<String> {
        val liveData = MutableLiveData<String>()
        liveData.value = "switchmap : "+str
        return liveData
    }

    fun onActionClick(v : View) {
        // change data
        videoData.value = VideoDownload(System.currentTimeMillis().toString())
    }

    fun onReActionClick(v : View) {
        // check data
        Toast.makeText(appContext, videoName.value, Toast.LENGTH_LONG).show()
    }

}

对我来说,这是因为观察者所有者是一个片段。它在导航到不同的片段时停止触发。我将观察者所有者更改为 activity 并按预期触发。

itemsViewModel.items.observe(requireActivity(), Observer {

视图模型定义为 class 属性:

    private val itemsViewModel: ItemsViewModel by lazy {
    ViewModelProvider(requireActivity()).get(ItemsViewModel::class.java)
}

如果你真的想让它被触发。

fun <X, Y> LiveData<X>.forceMap(
    mapFunction: (X) -> Y
): LiveData<Y> {
    val result = MutableLiveData<Y>()
    this.observeForever {x->
        if (x != null) {
            result.value = mapFunction.invoke(x)
        }
    }
    return result
}