Room Debugging DAO in Android: Simplify your workflow

This blog post explains how to create a space for DAOS for your Android debugging build. These debug-only DAOs enable you to implement developer-centric features without affecting your production applications.
Keeping the code base clean is essential for long-term maintainability. DAOs only achieve this by isolating developer tools from user-facing features.
Consider an application that caches and displays items. The “Delete All Projects” feature, while helpful to developers, should not be contacted by users. A separate debug DAO provides this feature without messing up your production code or confusing the core functionality of your application.
So, let’s get started! We use space for the database, which is not a room tutorial, so it requires some previous familiarity. 🙂
When you use the room persistent library to store application data, you can interact with the stored data by defining it Data access objector Daos. Each DAO contains methods that provide abstract access to the application database. At compile time, the room will automatically generate an implementation of the DAO you defined.
First, we create a typical room database (all code available here):
@Database(entities = [Item::class], version = 1, exportSchema = false)
abstract class ShopDatabase : RoomDatabase() {
abstract fun itemDao(): ItemDao
companion object {
@Volatile
private var Instance: ShopDatabase? = null
/**
*
*/
fun getDatabase(context: Context): ShopDatabase {
return Instance ?: synchronized(this) {
Room.databaseBuilder(context, ShopDatabase::class.java, "shop_database")
.fallbackToDestructiveMigration()
}
.build()
.also { Instance = it }
}
}
}
Use a DAO that allows insertion and streaming of all values:
@Dao
interface ItemDao {
@Insert(onConflict = OnConflictStrategy.IGNORE)
suspend fun insert(item: Item)
@Query("SELECT * from items")
fun streamAll(): Flow>
}
Now magic. We will create a single interface with two different signatures based on the source group. Add a DAO that can remove all projects used to debug the application, as well as an empty extension interface for production applications (i.e. no additional behavior).
/**
* DAO extensions available in the debug source set only (matching interface in the release source set)
*/
interface DaoExtensions {
fun debugItemDao(): DebugItemDao
}
@Dao
interface DebugItemDao {
@Query("DELETE FROM items")
fun deleteAll()
}
/**
* DAO extensions available in the release source set only (matching interface in the debug source set)
*/
interface DaoExtensions {
// Nothing for release builds
}
Note that what we have in our debug and release sources:
To connect to this new extension interface, you simply add it to the abstract database definition:
@Database(entities = [Item::class], version = 1, exportSchema = false)
abstract class ShopDatabase : RoomDatabase(), DaoExtensions {
That’s it! This setting means that when the code is built and the code generation is started (this is how the room creates the actual database code), the debugging application will be able to access the deleteAll method in the database, the (Release) application application will not be able to access this code.
How you would use this feature is to have a “debug screen” for your application. The debug screen in an Android app is a hidden or special screen that developers use to get more information about the current status of the app and test different features. This is like a secret menu with tools that can help you find and solve problems. Example code for using with the blog (here) to do this here.
Congratulations! You have added database operations to the suite in your application debugging tool!
Thank you for listening.
All code can be found on Github.
Any questions you can find me:
bluesky @blundell_apps (or thread, or x,?)
A special shout out to Danny Santiago about expanding ideas.
enjoy!