O banco de dados Room oferece uma camada de abstração sobre o SQLite para permitir acesso fluente ao banco de dados e, ao mesmo tempo, aproveitar toda a capacidade do SQLite.
Apps que processam quantidades não triviais de dados estruturados podem se beneficiar muito da persistência desses dados localmente. O caso de uso mais comum é armazenar as partes de dados relevantes em cache. Dessa forma, quando o dispositivo não conseguir acessar a rede, o usuário ainda poderá navegar pelo conteúdo enquanto estiver off-line. Todas as modificações de conteúdo feitas pelo usuário serão sincronizadas com o servidor quando o dispositivo ficar on-line novamente.
É altamente recomendável usar o Room em vez do SQLite, porque o Room cuida desses problemas para você. No entanto, se você prefere usar APIs SQLite diretamente, leia Salvar dados usando o SQLite.
Para usar o Room no app, adicione as seguintes dependências ao arquivo build.gradle
do app:
Kotlin
dependencies { def room_version = "2.2.6" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" // optional - Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" }
Java
dependencies { def room_version = "2.2.6" implementation "androidx.room:room-runtime:$room_version" annotationProcessor "androidx.room:room-compiler:$room_version" // optional - RxJava support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" }
Existem três componentes principais no Room:
Banco de dados: contém o suporte do banco de dados e serve como o principal ponto de acesso para a conexão com dados relacionais e persistentes do app.
A classe que está anotada com
@Database
precisa atender às seguintes condições:- Ser uma classe abstrata que estende
RoomDatabase
; - Incluir a lista de entidades associadas ao banco de dados na anotação;
- Conter um método abstrato que tenha 0 argumentos e retorne a classe que é anotada com
@Dao
;
É possível adquirir uma instância de
Database
chamandoRoom.databaseBuilder()
ouRoom.inMemoryDatabaseBuilder()
durante a execução.- Ser uma classe abstrata que estende
Entidade: representa uma tabela dentro do banco de dados.
DAO: contém os métodos utilizados para acessar o banco de dados.
O app usa o banco de dados do Room para conseguir os objetos de acesso a dados (DAOs, na sigla em inglês) associados a esse banco de dados. Em seguida, o app usa cada DAO para conseguir entidades do banco de dados e salvar as alterações dessas entidades de volta no banco de dados. Por fim, o app usa uma entidade para conseguir e definir valores que correspondam a colunas da tabela no banco de dados.
Essa relação entre os diferentes componentes do Room aparece na Figura 1:

O snippet de código a seguir contém uma configuração de banco de dados de exemplo, com uma entidade e um DAO.
User
Kotlin
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String?, @ColumnInfo(name = "last_name") val lastName: String? )
Java
@Entity public class User { @PrimaryKey public int uid; @ColumnInfo(name = "first_name") public String firstName; @ColumnInfo(name = "last_name") public String lastName; }
UserDao
Kotlin
@Dao interface UserDao { @Query("SELECT * FROM user") fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") fun loadAllByIds(userIds: IntArray): List<User> @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") fun findByName(first: String, last: String): User @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) }
Java
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user); }
AppDatabase
Kotlin
@Database(entities = arrayOf(User::class), version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
Java
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
Após criar os arquivos acima, é possível conseguir uma instância do banco de dados criado usando o seguinte código:
Kotlin
val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()
Java
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
Observação: se seu app é executado em um único processo, siga o padrão de projeto singleton ao instanciar um objeto AppDatabase
. Cada instância
RoomDatabase
é bastante cara e raramente é necessário ter acesso a várias instâncias em um único processo.
Se seu app é executado em vários processos, inclua enableMultiInstanceInvalidation()
na invocação do criador do banco de dados. Dessa forma, quando você tiver uma instância de AppDatabase
em cada processo, será possível invalidar o arquivo do banco de dados compartilhado em um processo. Essa invalidação será automaticamente propagada para as instâncias de AppDatabase
em outros processos.
Para ter uma experiência prática com o Room, veja os codelabs Android Room com visualização e Persistência Android (links em inglês). Para navegar por exemplos de código do Room, veja os exemplos de Componentes da Arquitetura do Android (link em inglês).