【问题标题】:Sharing display state between views in MVVM without relying on singletons在不依赖单例的情况下,在 MVVM 中的视图之间共享显示状态
【发布时间】:2019-06-12 17:36:43
【问题描述】:

我的应用程序有几个由不同片段用户启动的长进程,我想在它们完成时显示一个进度对话框。我希望这个进度对话框显示在几个片段中,以便仍然启用底部导航,这样用户仍然有一种代理感,但他们不能采取任何实际有害的行动。我的大部分“主要”片段都以这种方式被屏蔽,但其他如设置和帮助片段则不需要。

我目前的解决方案不太理想。动作是在片段中由用户启动的,但活动负责实际完成它们,因此它可以在需要的每个片段上覆盖一个进度对话框。我宁愿让片段负责自己的任务。 明显的关注点分离变得非常重要,因为活动 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
    }
}

我想到的另一个解决方案是将视图状态推送到模型层。似乎这需要一个单例(和一堆并发保护工作),以便视图模型无法开始覆盖状态,因为它正在完成这些长期运行的任务之一。目前这是自动避免的,因为只有一个活动虚拟机处理所有工作。

那么,有没有可能在不依赖模型层中的单例的情况下实现这种关注点分离?

【问题讨论】:

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


    【解决方案1】:

    我不会让 Activity(也不是 Fragments)承担这样的责任。它们是你无法摆脱的东西的 policyDelegates(谷歌使用的名称)(你需要一个或另一个才能让你的应用程序运行)。所以他们应该只做他们更了解的事情:

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

    那我该怎么办?

    • 有一个 LongProcessesManager(名字是你 2),它能够启动、停止和管理 N 个“进程”。它还必须提供指示所述过程进展的方法。
    • 拥有一个 ProcessFragment,它能够使用所述管理器来启动和接收 进程 的更新(它可以对所述结果采取行动,例如更新进度条)。
    • 如果您需要显示 GLOBAL 进度,您也可以这样做,您的 Activity 可以承载多个片段,因此没有什么可以阻止您在屏幕上放置第二个片段,该片段在有进度时不会消失(如例如音乐播放器)或其他什么,我不知道你的 UI :)
    • 考虑将上述管理器的管理移至可以成为前台的服务(如果这是必要的)(用户点击“主页”或离开您的应用以接听电话或查看 instagram,同时等待您的长时间运行的进程)。
    • 使用 DependencyInjection(Dagger,Koin,你选择),这样你就有了这个管理器的一个实例,它被注入到所有片段中(或者如果你想要共享 ViewModels)。

    这只是一个列表,其中列出了如果我被委以此类任务,我会开箱即用地做一些事情。

    【讨论】:

    • 这是一些值得思考的好东西,但据我所知,您的帖子归结为“使用单例”(仅由 DI 框架管理)。
    • 是的,当然;如果使用得当,单身人士并不是坏主意。你需要一个可以管理多件事情的人,而你不想要多个“人”,因为那样就没有意义了。有其他选择,但在某种程度上,您需要在某个地方放弃每项工作的进度,以协调所有这些工作。为什么你对单身人士如此执着? (好奇):)
    • 老实说,因为我只从书籍中学习架构和设计模式,其中大多数都说“尽可能避免单例”。我看到了它们的价值,我只是希望这是一个可以避免它们的案例。
    猜你喜欢
    • 2011-06-03
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    相关资源
    最近更新 更多