我有一个需要执行任务的队列。任务有两种类型:片段工作和后台工作。但我想把所有的工作代码都放在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)
}
您可以尝试编写一个单例类,您还可以隐藏该类中与 GPS 相关的事物的实现细节,并将其注入到视图模型中以完成您在视图模型中所做的工作。