music: use factory pattern in service components

This commit is contained in:
Alexander Capehart 2024-09-13 13:35:43 -06:00
parent d2aed8ee23
commit 8418dccdc6
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 54 additions and 33 deletions

View file

@ -41,13 +41,14 @@ class AuxioService :
MediaBrowserServiceCompat(), ForegroundListener, MusicServiceFragment.Invalidator {
@Inject lateinit var playbackFragment: PlaybackServiceFragment
@Inject lateinit var musicFragment: MusicServiceFragment
@Inject lateinit var musicFragmentFactory: MusicServiceFragment.Factory
lateinit var musicFragment: MusicServiceFragment
@SuppressLint("WrongConstant")
override fun onCreate() {
super.onCreate()
sessionToken = playbackFragment.attach(this)
musicFragment.attach(this, this)
musicFragment = musicFragmentFactory.create(this, this, this)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

View file

@ -36,10 +36,9 @@ import org.oxycblt.auxio.playback.state.PlaybackStateManager
import org.oxycblt.auxio.util.getSystemServiceCompat
import org.oxycblt.auxio.util.logD
class Indexer
@Inject
constructor(
@ApplicationContext override val workerContext: Context,
class Indexer private constructor(
override val workerContext: Context,
private val foregroundListener: ForegroundListener,
private val playbackManager: PlaybackStateManager,
private val musicRepository: MusicRepository,
private val musicSettings: MusicSettings,
@ -50,10 +49,21 @@ constructor(
MusicRepository.IndexingListener,
MusicRepository.UpdateListener,
MusicSettings.Listener {
class Factory @Inject constructor(
private val playbackManager: PlaybackStateManager,
private val musicRepository: MusicRepository,
private val musicSettings: MusicSettings,
private val imageLoader: ImageLoader,
private val contentObserver: SystemContentObserver
) {
fun create(context: Context, listener: ForegroundListener) =
Indexer(context, listener, playbackManager,
musicRepository, musicSettings, imageLoader, contentObserver)
}
private val indexJob = Job()
private val indexScope = CoroutineScope(indexJob + Dispatchers.IO)
private var currentIndexJob: Job? = null
private var foregroundListener: ForegroundListener? = null
private val indexingNotification = IndexingNotification(workerContext)
private val observingNotification = ObservingNotification(workerContext)
private val wakeLock =
@ -62,8 +72,7 @@ constructor(
.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, BuildConfig.APPLICATION_ID + ":IndexingComponent")
fun attach(listener: ForegroundListener) {
foregroundListener = listener
init {
musicSettings.registerListener(this)
musicRepository.addUpdateListener(this)
musicRepository.addIndexingListener(this)
@ -77,7 +86,6 @@ constructor(
musicRepository.addIndexingListener(this)
musicRepository.addUpdateListener(this)
musicRepository.removeIndexingListener(this)
foregroundListener = null
}
override fun requestIndex(withCache: Boolean) {
@ -91,7 +99,7 @@ constructor(
override val scope = indexScope
override fun onIndexingStateChanged() {
foregroundListener?.updateForeground(ForegroundListener.Change.INDEXER)
foregroundListener.updateForeground(ForegroundListener.Change.INDEXER)
val state = musicRepository.indexingState
if (state is IndexingState.Indexing) {
wakeLock.acquireSafe()
@ -132,7 +140,7 @@ constructor(
// the music loading process ends.
if (musicRepository.indexingState == null) {
logD("Not loading, updating idle session")
foregroundListener?.updateForeground(ForegroundListener.Change.INDEXER)
foregroundListener.updateForeground(ForegroundListener.Change.INDEXER)
}
}

View file

@ -37,24 +37,31 @@ import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.search.SearchEngine
class MusicBrowser
@Inject
constructor(
@ApplicationContext private val context: Context,
class MusicBrowser private constructor(
private val context: Context,
private val invalidator: Invalidator,
private val musicRepository: MusicRepository,
private val searchEngine: SearchEngine,
private val listSettings: ListSettings,
homeGeneratorFactory: HomeGenerator.Factory
) : MusicRepository.UpdateListener, HomeGenerator.Invalidator {
class Factory @Inject constructor(
private val musicRepository: MusicRepository,
private val searchEngine: SearchEngine,
private val listSettings: ListSettings,
private val homeGeneratorFactory: HomeGenerator.Factory
) {
fun create(context: Context, invalidator: Invalidator): MusicBrowser =
MusicBrowser(context, invalidator, musicRepository, searchEngine, listSettings, homeGeneratorFactory)
}
interface Invalidator {
fun invalidateMusic(ids: Set<String>)
}
private val homeGenerator = homeGeneratorFactory.create(this)
private var invalidator: Invalidator? = null
fun attach(invalidator: Invalidator) {
this.invalidator = invalidator
init {
musicRepository.addUpdateListener(this)
}
@ -64,7 +71,7 @@ constructor(
override fun invalidateMusic(type: MusicType, instructions: UpdateInstructions) {
val id = MediaSessionUID.Tab(TabNode.Home(type)).toString()
invalidator?.invalidateMusic(setOf(id))
invalidator.invalidateMusic(setOf(id))
}
override fun invalidateTabs() {
@ -72,7 +79,7 @@ constructor(
// TODO: Temporary bodge, move the amount parameter to a bundle extra
val rootId = MediaSessionUID.Tab(TabNode.Root(i)).toString()
val moreId = MediaSessionUID.Tab(TabNode.More(i)).toString()
invalidator?.invalidateMusic(setOf(rootId, moreId))
invalidator.invalidateMusic(setOf(rootId, moreId))
}
}

View file

@ -39,35 +39,40 @@ import org.oxycblt.auxio.util.logW
class MusicServiceFragment
@Inject
constructor(
@ApplicationContext private val context: Context,
private val indexer: Indexer,
private val musicBrowser: MusicBrowser,
private val context: Context,
foregroundListener: ForegroundListener,
private val invalidator: Invalidator,
indexerFactory: Indexer.Factory,
musicBrowserFactory: MusicBrowser.Factory,
private val musicRepository: MusicRepository
) : MusicBrowser.Invalidator {
private var invalidator: Invalidator? = null
private val indexer = indexerFactory.create(context, foregroundListener)
private val musicBrowser = musicBrowserFactory.create(context, this)
private val dispatchJob = Job()
private val dispatchScope = CoroutineScope(dispatchJob + Dispatchers.Default)
interface Invalidator {
fun invalidateMusic(mediaId: String)
class Factory @Inject constructor(
private val indexerFactory: Indexer.Factory,
private val musicBrowserFactory: MusicBrowser.Factory,
private val musicRepository: MusicRepository
) {
fun create(context: Context, foregroundListener: ForegroundListener, invalidator: Invalidator): MusicServiceFragment =
MusicServiceFragment(context, foregroundListener, invalidator, indexerFactory, musicBrowserFactory, musicRepository)
}
fun attach(foregroundListener: ForegroundListener, invalidator: Invalidator) {
this.invalidator = invalidator
indexer.attach(foregroundListener)
musicBrowser.attach(this)
interface Invalidator {
fun invalidateMusic(mediaId: String)
}
fun release() {
dispatchJob.cancel()
musicBrowser.release()
indexer.release()
invalidator = null
}
override fun invalidateMusic(ids: Set<String>) {
ids.forEach { mediaId ->
requireNotNull(invalidator) { "Invalidator not available" }.invalidateMusic(mediaId)
invalidator.invalidateMusic(mediaId)
}
}