You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LiveData值变更时switchMap未触发问题求助

问题:LiveData的switchMap未随currentList值变更触发

参考Android官方文档,预期当currentList的LiveData值变更时,activeTasks、completedTasks和importantTasks的LiveData数据会自动更新,进而触发观察者更新UI。但实际currentList值变更时,绑定的switchMap完全未被触发。

以下是原项目的ViewModel代码:

class AppViewModel(application: Application) : AndroidViewModel(application) {

    companion object {
        const val TAG: String = "AppViewModel"
    }

    private val dataSource: TaskDao

    val lists: LiveData<List<TaskList>>
    var lastAction: Int = 1
    val currentList = MutableLiveData(1)

    var currentIndex: Int = -1
        set(value) {
            field = value
            Log.d(TAG, "currentIndex setter: index = $field")
        }

    init {
        val db = AppDatabase.getInstance(application)
        dataSource = db.taskDao()
        lists = dataSource.getAllLists()
    }

    fun importantTasks(): LiveData<List<Task>> = currentList.switchMap {
        // 用于跟踪变化,由此确认switchMap未被触发
        Log.d(TAG, "importantTasks: updated")

        dataSource.getImportant(it)
    }

    fun activeTasks(): LiveData<List<Task>> = currentList.switchMap {
        Log.d(TAG, "activeTasks: updated")
        dataSource.getActiveTasks(it)
    }

    fun completedTasks(): LiveData<List<Task>> = currentList.switchMap {
        Log.d(TAG, "completedTasks: updated")
        dataSource.getCompletedTasks(it)
    }

    fun setCurrentList(id: Int){
        currentList.value = id
    }

    fun upsert(task: Task) = viewModelScope.launch(Dispatchers.IO) {
        task.listId = currentList.value!!
        dataSource.upsert(task)
        Log.d(TAG, "upsert: task upserted at ${task.listId}")
    }

    fun delete(task: Task) = viewModelScope.launch(Dispatchers.IO) {
        task.listId = currentList.value!!
        dataSource.delete(task)
        Log.d(TAG, "delete: task deleted at ${task.listId}")
    }

    fun upsertList(list: TaskList) = viewModelScope.launch(Dispatchers.IO) {
        dataSource.upsertList(list)
        Log.d(TAG, "upsertList: updated: id = ${list.id} , name = ${list.name}")
    }
}

通过如下方式修改currentList的值:

override fun onItemClicked(id: Int) {
    viewModel.setCurrentList(id)
    dismiss()
}

更新:在新项目中测试该逻辑可正常运行,测试代码如下:

测试用ViewModel代码:

class AppViewModel : ViewModel() {

    val listId = MutableLiveData(0)

    fun getUsers(): LiveData<List<User>> = listId.switchMap {
        Log.d("AppViewModel", "getUsers: updated")
        data(it)
    }

    fun data(id: Int): LiveData<List<User>> {
        val users = if (id == 0) List(30) { i -> User(i, "User$i", "password$i") }
        else List(25) { i -> User(i, "User$i", "password$i") }
        return MutableLiveData(users)
    }
}

修改listId值的方式:

class MainActivity : ComponentActivity() {
    val viewModel: AppViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val text = findViewById<TextView>(R.id.textCounter)
        val button = findViewById<Button>(R.id.buttonSwitch)

        viewModel.getUsers().observeForever{
            Log.d("MainActivity", "onCreate: observer triggered")
            text.text = "${it.size}"
        }
        button.setOnClickListener {
            viewModel.listId.value = if (viewModel.listId.value == 1) 0 else 1
        }
    }
}

第一个项目使用RoomDatabase,测试项目用模拟数据集,怀疑这可能是问题根源,但不确定。

内容的提问来源于stack exchange,提问作者Hna Naut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:09:52