在不依赖单例的情况下在MVVM中的视图之间共享显示状态

时间:2019-06-12 17:36:43

标签: android android-fragments design-patterns mvvm architecture

我的应用程序有多个较长的进程,这些进程由用户启动,并由不同的片段组成,我想在完成时显示进度对话框。我希望此进度对话框显示在多个片段中,以便仍启用底部导航,以便用户仍然有一种代理感,但是他们不能采取其他实际上有害的措施。我的大部分“主要”片段都以这种方式被阻止,但是其他设置(例如设置和帮助片段)则不需要。

我当前的解决方案不理想。动作是用户在片段中启动的,但是活动负责实际完成它们,因此它可以将进度对话框覆盖在所需的每个片段上。我宁愿片段负责自己的任务。 随着活动VM的规模变得越来越大,并且该类中过多的业务逻辑(然后适当地委派给该模型),关注点之间的明显分离变得非常重要。

例如

class MyFragment : Fragment() {
    // MyActivity will implement this interface
    interface NetworkProcess {
        fun start()
    }
    // start() is called on a button click or something similar
}

class MyActivity : AppCompatActivity(), MyFragment.NetworkProcess {
    override fun onCreate(savedInstanceBundle: Bundle?) {
        // Observe state from VM layer
        // Observer updates progress dialog
    }
    override fun start() {
        // Pass action to VM layer
     }
}

我尝试过的一种解决方案是仅将界面用于显示状态,但是如果该片段被导航离开,则无法调用该界面并继续更新对话框。

例如

class MyFragment : Fragment() {
    // MyActivity will implement this interface
    interface NetworkProcessDialog {
        fun update(text: Int)
        fun stop()
    }
    override fun onActivityCreated() {
        // Observe state from viewmodel
        // Set listener on a button send action to viewmodel to start process
    }
}

class MyActivity : AppCompatActivity(), MyFragment.NetworkProcessDialog {
    override fun updateDialog(text: Int) {
        // Make dialog visible if not and show update
     }
    override fun stopDialog() {
        // Make dialog invisible
    }
}

我想到的另一种解决方案是将视图状态推入模型层。似乎这将需要单身人士(和一堆并发保护工作),以便在完成这些长时间运行的任务之一的过程中,视图模型无法开始覆盖状态。由于只有一个活动VM处理所有工作,因此目前可以自动避免这种情况。

那么,有可能在不依赖模型层中单例的情况下进行关注点分离吗?

1 个答案:

答案 0 :(得分:1)

我不会让活动(也不是片段)承担这样的责任。它们是policyDelegates(由Google使用的名称),用于处理您无法摆脱的事情(需要一个或另一个来运行您的应用)。因此,他们应该只做自己更了解的事情:

  • 处理生命周期(无法解决)
  • 添加视图并显示
  • 保存/恢复其状态(如果可能)
  • 片段之间的接口(如果需要)
  • 接收状态更新并将其反映在相应的视图中

那我该怎么办?

  • 具有LongProcessesManager(名称最多为2个),该功能能够启动,停止和管理N个“进程”。它还必须提供指示该过程进度的方法。
  • 具有一个能够使用所述管理器启动并接收进程的更新的ProcessFragment(它可以对所述结果进行操作,例如更新进度条)。
  • 如果您需要显示GLOBAL进度,也可以这样做,您的活动可以托管1个以上的片段,因此没有什么可以阻止您将第二个片段放到屏幕上,而该片段不会随着进度而消失(例如音乐播放器)或其他任何内容,我都不知道您的用户界面:)
  • 考虑将上述Manager的管理移至可以成为前台的服务(如果需要的话)(用户按“ Home”或离开您的应用以接听电话或检查instagram,而他们正在等待您长时间运行的进程) )。
  • 使用DependencyInjection(Dagger,Koin,您选择),以便您拥有该管理器的单个实例,该实例将注入所有片段(如果需要,也可以共享Shared ViewModels)。

如果我要执行类似的任务,这只是一些开箱即用的事情的清单。