为什么方法在DAO方法之后不返回任何内容?

发布于 2025-02-03 10:04:01 字数 1655 浏览 3 评论 0原文

我的代码在呼叫dao方法后停止工作,如果我使用GlobalScope代码工作,但是Livedata不更新更改

override suspend fun addNewTask(title: String,priority : Int,date: Date): Boolean {
    var isSuccess = false

    val newTask = hashMapOf(
        "title" to title,
        "priority" to priority,
        "task_points" to converterListOfListToJson(listOf()),
        "date" to Timestamp(date)
    )

    val user: User? = userDao.getCurrentUser()
    val newTaskList = user?.tasks?.toMutableList()
    val generatedDoc = db.collection(CollectionNames.tasks).document()
    val userTasks = db.collection(CollectionNames.users).document(user!!.id)

    generatedDoc.set(newTask)
        .addOnSuccessListener { isSuccess = true }
        .addOnFailureListener { Log.e(TAG, "Error writing document") }.await()

    userTasks.update(
        "tasks", FieldValue.arrayUnion(generatedDoc.id)
    ).await()

    newTaskList?.add(generatedDoc.id)
    
    taskDao.insert(Task(generatedDoc.id, title, date, listOf(), priority.toLong())) //after code out

    user.tasks = newTaskList!!.toList()

    userDao.updateUser(user)

    return isSuccess
}

此方法的调用,AddNewTask已完整完成,但是

fun createTask(title : String, priority : String,date: Date) {
    viewModelScope.launch{
        tasksUseCase.addNewTask(title, priority, date)
        tasksUseCase.updateTaskFromLocalDB().collect { //it is not called
            _taskList.postValue(it)
        }

    }
}

在代码仅结束DAO之后,我只使用注释更新并插入我的函数调用,然后插入

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(task: Task)

我的函数呼叫对话框片段单击,但使用父片片段的ViewModel,函数僵局,没有错误

My code stop working after call dao method, if I use GlobalScope code working, but then LiveData not update changes

override suspend fun addNewTask(title: String,priority : Int,date: Date): Boolean {
    var isSuccess = false

    val newTask = hashMapOf(
        "title" to title,
        "priority" to priority,
        "task_points" to converterListOfListToJson(listOf()),
        "date" to Timestamp(date)
    )

    val user: User? = userDao.getCurrentUser()
    val newTaskList = user?.tasks?.toMutableList()
    val generatedDoc = db.collection(CollectionNames.tasks).document()
    val userTasks = db.collection(CollectionNames.users).document(user!!.id)

    generatedDoc.set(newTask)
        .addOnSuccessListener { isSuccess = true }
        .addOnFailureListener { Log.e(TAG, "Error writing document") }.await()

    userTasks.update(
        "tasks", FieldValue.arrayUnion(generatedDoc.id)
    ).await()

    newTaskList?.add(generatedDoc.id)
    
    taskDao.insert(Task(generatedDoc.id, title, date, listOf(), priority.toLong())) //after code out

    user.tasks = newTaskList!!.toList()

    userDao.updateUser(user)

    return isSuccess
}

This call of this method, addNewTask full complete but after code just end method

fun createTask(title : String, priority : String,date: Date) {
    viewModelScope.launch{
        tasksUseCase.addNewTask(title, priority, date)
        tasksUseCase.updateTaskFromLocalDB().collect { //it is not called
            _taskList.postValue(it)
        }

    }
}

In DAO I just use annotation update and insert

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(task: Task)

My function call in dialog fragment on click, but with viewModel of parent fragment, function deadlock without errors

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独患者 2025-02-10 10:04:01

.addonSuccessListener {issuccess = true}将在将来将变量更改为True,以后在后台完成工作。您使用issuccess的代码在有机会完成背景工作之前被调用。

当您使用GlobalsCope时,它可能使用默认调度程序dispatcher.default,因此您患有种族条件,在某些情况下可能会成功。

当您使用viewModelsCope时,它使用dispatcher.main,因此在此暂停功能结束之前,不可能调用结果侦听器介于两者之间。

修复它需要做的是以同步,悬挂方式而不是异步方式来运行任务。由于我不知道什么类生成的Doc是,所以我无能为力。许多库都包含扩展悬挂函数,通常命名为等待(),可让您同步获得结果。如果他们不提供,则可以使用suppendCancellableCoroutine来编写自己的编写。您可以在这里进行许多其他问题,您可以搜索如何使用它。

.addOnSuccessListener { isSuccess = true } will change the variable to true some time in the future, when the background work is done. Your code that uses isSuccess is called before it has a chance to finish the background work.

When you used GlobalScope, it probably used the default dispatcher Dispatchers.Default, so you had a race condition and in some cases it could succeed.

When you used viewModelScope, it uses Dispatchers.Main, so there is no possibility of the result listener being called before the end of this suspend function unless there is some other suspending call in between.

What you need to do to fix it is run your task in a synchronous, suspending way instead of an asynchronous way. Since I don't know what class generatedDoc is, I can't help with that. Many libraries include extension suspend function, usually named await(), that let you get the result synchronously. If they don't provide that, you can write your own using suspendCancellableCoroutine. There are many other questions about that on here that you can search for to see how to use it.

旧时光的容颜 2025-02-10 10:04:01

问题在于,ViewModel是一个对话fragment,在调用该方法后被销毁,因此ViewModelScope也不再存在,并且该方法崩溃了

The problem was that the viewModel was a DialogFragment which was destroyed after the method was called, due to which the ViewModelScope also ceased to exist and the method crashed in the middle

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文