all: inject room dbs

Inject room databases instead of lazily creating them.

This should make repositories much easier to test.
This commit is contained in:
Alexander Capehart 2023-02-12 19:15:11 -07:00
parent dd2017c510
commit e017d53139
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 49 additions and 86 deletions

View file

@ -17,14 +17,12 @@
package org.oxycblt.auxio.music.cache
import android.content.Context
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Entity
import androidx.room.Insert
import androidx.room.PrimaryKey
import androidx.room.Query
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverter
import androidx.room.TypeConverters
@ -36,35 +34,6 @@ import org.oxycblt.auxio.music.model.RawSong
@Database(entities = [CachedSong::class], version = 27, exportSchema = false)
abstract class CacheDatabase : RoomDatabase() {
abstract fun cachedSongsDao(): CachedSongsDao
companion object {
@Volatile private var INSTANCE: CacheDatabase? = null
/**
* Get/create the shared instance of this database.
* @param context [Context] required.
*/
fun getInstance(context: Context): CacheDatabase {
val instance = INSTANCE
if (instance != null) {
return instance
}
synchronized(this) {
val newInstance =
Room.databaseBuilder(
context.applicationContext,
CacheDatabase::class.java,
"auxio_tag_cache.db")
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigrationFrom(0)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
INSTANCE = newInstance
return newInstance
}
}
}
}
@Dao

View file

@ -17,10 +17,15 @@
package org.oxycblt.auxio.music.cache
import android.content.Context
import androidx.room.Room
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.oxycblt.auxio.music.extractor.CacheRepository
import org.oxycblt.auxio.music.extractor.CacheRepositoryImpl
@ -29,3 +34,19 @@ import org.oxycblt.auxio.music.extractor.CacheRepositoryImpl
interface CacheModule {
@Binds fun cacheRepository(cacheRepository: CacheRepositoryImpl): CacheRepository
}
@Module
@InstallIn(SingletonComponent::class)
class CacheRoomModule {
@Singleton
@Provides
fun database(@ApplicationContext context: Context) =
Room.databaseBuilder(
context.applicationContext, CacheDatabase::class.java, "music_cache.db")
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigrationFrom(0)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
@Provides fun cachedSongsDao(database: CacheDatabase) = database.cachedSongsDao()
}

View file

@ -17,10 +17,7 @@
package org.oxycblt.auxio.music.extractor
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.oxycblt.auxio.music.cache.CacheDatabase
import org.oxycblt.auxio.music.cache.CachedSong
import org.oxycblt.auxio.music.cache.CachedSongsDao
import org.oxycblt.auxio.music.model.RawSong
@ -44,12 +41,8 @@ interface CacheRepository {
suspend fun writeCache(rawSongs: List<RawSong>)
}
class CacheRepositoryImpl @Inject constructor(@ApplicationContext private val context: Context) :
class CacheRepositoryImpl @Inject constructor(private val cachedSongsDao: CachedSongsDao) :
CacheRepository {
private val cachedSongsDao: CachedSongsDao by lazy {
CacheDatabase.getInstance(context).cachedSongsDao()
}
override suspend fun readCache(): Cache? =
try {
// Faster to load the whole database into memory than do a query on each

View file

@ -17,7 +17,6 @@
package org.oxycblt.auxio.playback.persist
import android.content.Context
import androidx.room.Dao
import androidx.room.Database
import androidx.room.Entity
@ -25,7 +24,6 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.PrimaryKey
import androidx.room.Query
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverter
import androidx.room.TypeConverters
@ -61,35 +59,6 @@ abstract class PersistenceDatabase : RoomDatabase() {
/** @see [Music.UID.fromString] */
@TypeConverter fun toMusicUid(string: String?) = string?.let(Music.UID::fromString)
}
companion object {
@Volatile private var INSTANCE: PersistenceDatabase? = null
/**
* Get/create the shared instance of this database.
* @param context [Context] required.
*/
fun getInstance(context: Context): PersistenceDatabase {
val instance = INSTANCE
if (instance != null) {
return instance
}
synchronized(this) {
val newInstance =
Room.databaseBuilder(
context.applicationContext,
PersistenceDatabase::class.java,
"auxio_playback_persistence.db")
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigrationFrom(1)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
INSTANCE = newInstance
return newInstance
}
}
}
}
/**

View file

@ -17,13 +17,38 @@
package org.oxycblt.auxio.playback.persist
import android.content.Context
import androidx.room.Room
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
interface PersistenceModule {
@Binds fun repository(persistenceRepository: PersistenceRepositoryImpl): PersistenceRepository
}
@Module
@InstallIn(SingletonComponent::class)
class PersistenceRoomModule {
@Singleton
@Provides
fun database(@ApplicationContext context: Context) =
Room.databaseBuilder(
context.applicationContext,
PersistenceDatabase::class.java,
"playback_persistence.db")
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigrationFrom(1)
.fallbackToDestructiveMigrationOnDowngrade()
.build()
@Provides fun playbackStateDao(database: PersistenceDatabase) = database.playbackStateDao()
@Provides fun queueDao(database: PersistenceDatabase) = database.queueDao()
}

View file

@ -17,8 +17,6 @@
package org.oxycblt.auxio.playback.persist
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import org.oxycblt.auxio.music.MusicParent
import org.oxycblt.auxio.music.model.Library
@ -43,22 +41,12 @@ interface PersistenceRepository {
* @param state The [PlaybackStateManager.SavedState] to persist.
*/
suspend fun saveState(state: PlaybackStateManager.SavedState?): Boolean
companion object {
/**
* Get a framework-backed implementation.
* @param context [Context] required.
*/
fun from(context: Context): PersistenceRepository = PersistenceRepositoryImpl(context)
}
}
class PersistenceRepositoryImpl
@Inject
constructor(@ApplicationContext private val context: Context) : PersistenceRepository {
private val database: PersistenceDatabase by lazy { PersistenceDatabase.getInstance(context) }
private val playbackStateDao: PlaybackStateDao by lazy { database.playbackStateDao() }
private val queueDao: QueueDao by lazy { database.queueDao() }
constructor(private val playbackStateDao: PlaybackStateDao, private val queueDao: QueueDao) :
PersistenceRepository {
override suspend fun readState(library: Library): PlaybackStateManager.SavedState? {
val playbackState: PlaybackState

View file

@ -146,8 +146,6 @@ class PlaybackService :
.build()
.also { it.addListener(this) }
replayGainProcessor.addToListeners(player)
// Initialize the core service components
persistenceRepository = PersistenceRepository.from(this)
foregroundManager = ForegroundManager(this)
// Initialize any listener-dependent components last as we wouldn't want a listener race
// condition to cause us to load music before we were fully initialize.