如何让viewmodel发起后台任务

问题描述 投票:0回答:1

我有一个需要执行任务的队列。任务有两种类型:片段工作和后台工作。但我想把所有的工作代码都放在viewmodel中统一管理。我应该如何设计框架?

当导航在后台工作时,我尝试使用 findNavController().popBackStack() 跳过 UI 显示,但 viewmodel 的任务也被取消。如果我将视图模型更改为 ActivityViewModel(),它可以工作,但也会导致状态无法清除。有什么好办法让viewmodel变成viewmodel()并且让fragment不可见吗

这是片段代码

@AndroidEntryPoint
class GpsFragment : XcBaseTaskFragment<FragmentBaseStartBinding>(), TaskHandler {


    val vm: XcBaseGpsViewModel by viewModels()


    override fun getLayoutResId(): Int {
        return R.layout.fragment_base_start
    }

    override fun initView() {
        super.initView()
        if (isBackgroundMode) {
            XLog.i("initView isBackgroundMode ${isBackgroundMode}")
            lifecycleScope.launcher {
                withContext(Dispatchers.Main) {
                    vm.startGps(GlobalScope)
//                    GpsUtils(vm.application).startGps(GlobalScope, { !(vm.satelliteCount.value!! > 0) },
//                        {
//                            withContext(Dispatchers.Main) {
//                                ToastUtils.showShort("satelliteCount ${vm.satelliteCount.value}")
//                            }
//                        },{})
                    delay(5000)
                    doNextTask()
//                    findNavController().popBackStack()
                }
            }
        }
    }


    override fun afterView() {
        super.afterView()
//        XLog.i("gps afterView")
        if (!isBackgroundMode) {
            binding.btStart.setOnClickListener {
                XLog.i("startGps setOnClickListener")
                lifecycleScope.launcher {
                    vm.startGps()
                }
            }
            vm.satelliteCount.observe(viewLifecycleOwner) {
                binding.tvStart.text = it.toString()
                if (it > 0) {
                    doNextTask()
            }
        }
        }
    }


    override fun onDestroyView() {
        super.onDestroyView()
        if (!isBackgroundMode) {
            vm.stopGpsTest()
        }
    }


    override suspend fun executeTaskLogic(t: XcBackgroundFragmentTask) {

//        GlobalScope.launcher {
//            baseTask = t
//            withContext(Main) {
//                GpsUtils(XcUtilsApp.instance).startGps()
//            }
////            vm.startGps()
//        }
    }
}

这是任务发送代码

type hereconst val ISBACKGROUNDMODE = "isBackgroundMode"

class XcBackgroundFragmentTask() : XcTask(), Parcelable {
    var handler: TaskHandler? = null
    open var navId: Int? = null

    override suspend fun doTask() {
        super.doTask()
        withContext(Dispatchers.Main) {
            if (XcTaskManager.getInstance().previousBackStackEntryId == null)
                XcTaskManager.getInstance().previousBackStackEntryId =
                    XcTaskManager.getInstance().navController?.currentDestination?.id
            navId?.let {
                if (!isBackground()) {
                    // 创建 Bundle 并添加参数
                    val bundle = Bundle().apply {
                        putParcelable("task", this@XcBackgroundFragmentTask)
                        putBoolean(ISBACKGROUNDMODE, isBackground())
                    }
                    XLog.i("putParcelable ${this@XcBackgroundFragmentTask}")
                    val navOptions = NavOptions.Builder()
                        .setPopUpTo(XcTaskManager.getInstance().previousBackStackEntryId!!, false)
                        .build()
                    XLog.i("doTask navId $it")
                    XcTaskManager.getInstance().navController?.navigate(it, bundle, navOptions)
                } else {

//                    handler?.executeTaskLogic(this@XcBackgroundFragmentTask)
                    val bundle = Bundle().apply {
                        putParcelable("task", this@XcBackgroundFragmentTask)
                        putBoolean(ISBACKGROUNDMODE, isBackground())
                    }
                    XcTaskManager.getInstance().navController?.navigate(it, bundle)
                }
            }
        }
    }

    override suspend fun finishTask() {
        if (!isBackground()) {
            withContext(Dispatchers.Main) {
                val isLastTask = XcTaskManager.getInstance().isLastTask()
                XLog.i("isLastTask ${isLastTask}")
                if (isLastTask) {
                    XcTaskManager.getInstance().previousBackStackEntryId?.let {
                        XcTaskManager.getInstance().navController?.popBackStack(
                            it,
                            false
                        )
                        XcTaskManager.getInstance().previousBackStackEntryId = null
                    }
                }
            }
        }
    }



    fun setTaskHandler(handler: TaskHandler) {
        this.handler = handler
    }

    fun setNavId(navId: Int) {
        XLog.i("navId $navId")
        this.navId = navId
    }
}

interface TaskHandler {
    suspend fun executeTaskLogic(task: XcBackgroundFragmentTask)
}
android kotlin fragment navigation-drawer viewmodel
1个回答
0
投票

您可以尝试编写一个单例类,您还可以隐藏该类中与 GPS 相关的事物的实现细节,并将其注入到视图模型中以完成您在视图模型中所做的工作。

© www.soinside.com 2019 - 2024. All rights reserved.