首次启动应用程序 Android Compose 时 UI 未正确更新

UI not updating properly on first launch of app Android Compose

提问人:JamieRhys 提问时间:7/6/2023 更新时间:7/6/2023 访问量:55

问:

我的 HomePageViewModel 中有以下代码:

private val _overallStitchCount: MutableStateFlow<Int> = MutableStateFlow(0)
    val overallStitchCount: StateFlow<Int> = _overallStitchCount

...

init {
        projectRepo = projectRepository
        projectRepo.refreshProjectData()
        populateValues()
    }

    fun populateValues() {
        _overallStitchCount.value = projectRepo.projectData.value.size
    }

    fun addProject() {
        val projectCount = projectRepo.projectData.value.size

        projectRepo.addProject(
            project = Project(
                uid = projectCount,
                projectName = "Example Project $projectCount"
            ),
            callback = { populateValues() }
        )
    }

如您所见,我正在使用 overallStitchCount 来测试我的数据库包含的内容。这是我在 ProjectRepository 类中的内容:

private val _projectData: MutableStateFlow<List<Project>> = MutableStateFlow(listOf())
    val projectData: StateFlow<List<Project>> = _projectData

...

init {
        CoroutineScope(Dispatchers.IO).launch {
            val data = getAllProjects()

            if(data.isEmpty()) {
                Log.i(LOG_TAG, "Generating example project data.")
                generateExampleProjectData()
            }
            else {
                _projectData.value = data
            }
        }
    }

...

fun addProject(
        project: Project,
        callback: (() -> Unit)? = null,
    ) {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                projectDao.addProject(project)
                _projectData.value = getAllProjects()
                if(callback != null) callback()
            }
            catch(e: Exception) {
                Log.e(LOG_TAG, "Exception: Could not create project ${project.projectName}. Reason: ${e.message}")
            }
        }
    }

    private fun generateExampleProjectData() {
        val project = Project(
            uid = 0,
            projectName = "Example Project"
        )
        addProject(
            project = project,
        )
    }

    fun refreshProjectData(
    ) {
        CoroutineScope(Dispatchers.IO).launch {
            val data = getAllProjects()

            if(data.size != _projectData.value.size) {
                Log.i(LOG_TAG, "Projects has changed, refreshing.")
                _projectData.value = getAllProjects()
            }
        }
    }

    fun getAllProjects(): MutableList<Project> {
        return try {
            projectDao.getAll()
        } catch(e: Exception) {
            Log.e(LOG_TAG, "Exception: ${e.message}")
            mutableListOf()
        } catch(e: SQLiteException) {
            Log.e(LOG_TAG, "Exception: ${e.message}")
            mutableListOf()
        }
    }

现在,在我的应用程序首次启动时,我的 UI 上的针迹计数显示为 0。此时应该说 3.

但是,当我点击UI上的“添加项目”按钮时,如果数据库计数为3,则会说4,这是正确的。

我将如何更改代码以便在初始启动时正确更新以读取数据库中的正确计数?

android-jetpack-compose 安卓房间 可变状态

评论

0赞 pushpull 7/6/2023
您在协程中调用 projectRepo.refreshProjectData() 并按顺序填充 Values。似乎在更新_projectData之前执行了 populateValues。您应该做的是将 init 的内容包装在 viewModelScope.launch 中,并从存储库中删除 coroutineScopes
0赞 JamieRhys 7/6/2023
所以基本上扭转了我当时的做法

答:

0赞 JamieRhys 7/6/2023 #1

我终于修好了(我想)。我将该方法更改为一个成熟的函数,而不是使用如下回调:ProjectRepositoryinit

fun init(
        callback: (() -> Unit)? = null,
    ) {
        CoroutineScope(Dispatchers.IO).launch {
            val data = getAllProjects()

            if(data.isEmpty()) {
                Log.i(LOG_TAG, "Generating example project data.")
                generateExampleProjectData()
            }
            else {
                _projectData.value = data
            }
            
            if(callback != null) callback()
        }
    }

然后我用我的:HomePageViewModelinit

init {
        projectRepo = projectRepository
        projectRepo.init(
            callback = { populateValues() }
        )
    }

它现在正在更新,正如我所期望的那样,在我的应用程序启动时,以及我可能有的任何进一步更新。