为什么我有多个“Player”实例?

Why do I have several instances of "Player"?

提问人:spCoder 提问时间:11/14/2023 更新时间:11/15/2023 访问量:56

问:

我正在开发一个具有音乐播放器功能的 android 应用程序。现在一切都在正常工作,但我对我这样做的方式不满意,所以我在这里。

该应用程序是 100% kotlin 100% compose。我正在使用 NavHost 在可组合屏幕之间导航。Here is a very badly diagram with the parts that are related to what I am interested

Main Activity 包含 NavHost。 NavHost 包含每个屏幕的所有导航和可组合项

每个屏幕(好吧,不是每个屏幕,而是大多数屏幕)我都使用一个 PlayerScaffold,它传递了一个顶部栏和一个内容,它们正常组成屏幕,但添加和更新了一个底部迷你播放器(a la spotify)和一个向上滑动的全屏模态播放器。

每个内容屏幕都有自己的视图模型,迷你播放器和完整播放器都有一个 PlayerViewModel。

PlayerViewModel 被传递一个“Player”的实例,该实例是一个保存 exoplayer 实例并执行所有游戏操作的类。

Player 类由 Dagger Hilt 实例化,并在模块中定义:

@Module
@InstallIn(SingletonComponent::class)
abstract class PlayerModule {

    @Binds
    abstract fun bindPlayer(
        playerImpl: PlayerImpl,
    ): Player
}

最重要的是,我有一个前台服务“PlayerService”来保存“Player”实例,以便在应用程序进入后台时保存,这样它就可以保存对玩家的引用并且不会被杀死。

我遇到的问题(现在已解决)是正在创建 PlayerViewModel 和 Player 的多个实例,因此如果我开始在一个屏幕中播放歌曲,然后转到下一个屏幕,下一个屏幕中的播放器将无法正确更新。我通过在 Application 类中保存 PlayerViewModel 的实例来解决它,因此只创建了一个实例,但我非常不确定这种方法。

我期望它的工作方式是每个组合屏幕都有一个 PlayerViewModel 的实例,但 Player 的实例对于所有 ViewModel 都是相同的。

如果 Player 类被注释为“Singleton”,为什么我有多个实例?

Android MVVM 匕首刀柄

评论


答:

1赞 spCoder 11/15/2023 #1

我想通了,这里的问题出在我将其注释为

@InstallIn(SingletonComponent::class)

而我没有阅读文档,认为这意味着它会自动使该模块中的所有内容成为“单例”

向函数添加@Singleton解决了该问题。无需将视图模型的实例保留在任何地方,现在它按预期工作。

@Module
@InstallIn(SingletonComponent::class)
abstract class PlayerModule {

    @Singleton
    @Binds
    abstract fun bindPlayer(
        playerImpl: PlayerImpl,
    ): Player
}