我正在开发一个具有音乐播放器功能的安卓应用。目前一切都正常运作,但我对自己的实现方式并不满意,所以我来这里寻求帮助。
这个应用是100%使用Kotlin和Compose编写的。我在可组合屏幕之间使用NavHost进行导航。
主活动包含NavHost。
NavHost包含所有的导航和可组合屏幕。
每个屏幕(不是每一个,但大多数)我都使用了一个PlayerScaffold,它接收一个顶部工具栏和内容,并正常地组合屏幕,但添加和更新了一个底部迷你播放器(类似Spotify)和一个可以向上滑动的全屏模态播放器。
每个内容屏幕都有自己的ViewModel,而迷你播放器和全屏播放器则有一个PlayerViewModel。
PlayerViewModel接收一个"Player"的实例,它是一个持有ExoPlayer实例并执行所有播放操作的类。
Player类由Dagger Hilt实例化,并在一个模块中定义。
此外,我还有一个前台服务“PlayerService”,用于在应用程序转到后台时保存“Player”实例,以便它可以保持对播放器的引用,避免被销毁。
我遇到的问题(现在已解决)是多个PlayerViewModel和Player实例被创建,因此如果我在一个屏幕上开始播放一首歌曲,然后切换到下一个屏幕,下一个屏幕上的播放器不会正确更新。我通过在Application类中持有PlayerViewModel的实例来解决这个问题,这样只会创建一个实例,但我对这种方法非常不确定。
我预期的工作方式是每个Compose屏幕都有一个PlayerViewModel的实例,但Player的实例对于所有ViewModel都是相同的。
如果Player类被注释为“Singleton”,为什么会有多个实例呢?
这个应用是100%使用Kotlin和Compose编写的。我在可组合屏幕之间使用NavHost进行导航。
![这是一个非常糟糕的图示,展示了我感兴趣的部分](https://istack.dev59.com/BsFbL.webp)
每个屏幕(不是每一个,但大多数)我都使用了一个PlayerScaffold,它接收一个顶部工具栏和内容,并正常地组合屏幕,但添加和更新了一个底部迷你播放器(类似Spotify)和一个可以向上滑动的全屏模态播放器。
每个内容屏幕都有自己的ViewModel,而迷你播放器和全屏播放器则有一个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的实例来解决这个问题,这样只会创建一个实例,但我对这种方法非常不确定。
我预期的工作方式是每个Compose屏幕都有一个PlayerViewModel的实例,但Player的实例对于所有ViewModel都是相同的。
如果Player类被注释为“Singleton”,为什么会有多个实例呢?