Room
Room 持久性库在 SQLite 的基础上提供了一个抽象层,让用户能够在充分利用 SQLite 的强大功能的同时,获享更强健的数据库访问机制
Android数据持久层直接使用SQLite很麻烦,Google官方推出了Room,
Google对Room的定义: The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
(Room是SQLite之上的一个抽象层,通过Room层来摆脱,繁琐的数据库操作,包括创建、更新数据库、表以及进行增删查改等)
另外多说一句,就个人而言,androidx包一定会成为主流,来替代各种版本的support包,所以如果你还没有使用上androidx,那么请早些使用。
首先我们先搞清楚为什么学习room
1.先看jetpack的框架
2. 再看官方文档的说明.
Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。
处理大量结构化数据的应用可极大地受益于在本地保留这些数据。最常见的用例是缓存相关数据。这样,当设备无法访问网络时,用户仍可在离线状态下浏览相应内容。设备之后重新连接到网络后,用户发起的所有内容更改都会同步到服务器。
由于 Room 负责为您处理这些问题,因此我们强烈建议您使用 Room(而不是 SQLite)。
3. jetpack学习的必要
JetPack更多是一种概念和态度。相当于Google把自己的Android生态重新整理了一番。确立了Android未来的版图和大方向。
JetPack里目前包含的内容,未来也会是Google大力维护和扩展的内容。对应开发者来说也是值得去学习使用的且相对无后顾之忧的。JetPack里没有的,除开一些优秀的第三方库,未来应该也会慢慢被新的API替代,逐渐边缘化,直至打上Deprecate注解。
以当下的环境来说,要开发出一个完全摆脱JetPack的APP是很难做到的。但是反过来讲JetPack也远远没有到成熟的地步,目前也还存在亟待解决的问题,未来可以做的事情还有很多。
关于使用的话,并不是所有库都建议使用,因为目前还有很多库在alpha版本。但是作为学习还是很有必要的,能给你日常的开发中多提供一些思路,这些是无可厚非的。
总的来说,JetPack的推广对广大开发者而言是利远远大于弊的。
Room 包含 3 个主要组件:
Entity(实体)
Dao(访问数据库操作的一个接口
Database(数据库的实际操作)
-
数据库:包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点。
使用
@Database
注释的类应满足以下条件:- 是扩展
RoomDatabase
的抽象类。 - 在注释中添加与数据库关联的实体列表。
- 包含具有 0 个参数且返回使用
@Dao
注释的类的抽象方法。
在运行时,您可以通过调用 [
Room.databaseBuilder()
](https://developer.android.google.cn/reference/androidx/room/Room?hl=zh_cn#databaseBuilder(android.content.Context, java.lang.Class, java.lang.String)) 或 [Room.inMemoryDatabaseBuilder()
](https://developer.android.google.cn/reference/androidx/room/Room?hl=zh_cn#inMemoryDatabaseBuilder(android.content.Context, java.lang.Class)) 获取Database
的实例。 - 是扩展
-
Entity:表示数据库中的表。
-
DAO:包含用于访问数据库的方法。
应用使用 Room 数据库来获取与该数据库关联的数据访问对象 (DAO)。然后,应用使用每个 DAO 从数据库中获取实体,然后再将对这些实体的所有更改保存回数据库中。最后,应用使用实体来获取和设置与数据库中的表列相对应的值。
Room 不同组件之间的关系如图 所示:
Room 具有以下注解处理器选项:
- room.schemaLocation:配置并启用将数据库架构导出到给定目录中的 JSON 文件的功能。
- room.incremental:启用 Gradle 增量注解处理器。
- room.expandProjection:配置 Room 以重写查询,使其顶部星形投影在展开后仅包含 DAO 方法返回类型中定义的列。
android {
...
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [
"room.schemaLocation":"$projectDir/schemas".toString(),
"room.incremental":"true",
"room.expandProjection":"true"]
}
}
}
}
room在jetpack中的位置
–
新建简单案例进行理解
1. 首先需要添加依赖
声明依赖项
要添加 Room 的依赖项,您必须将 Google Maven 代码库添加到项目中。
在应用或模块的 build.gradle 文件中添加所需工件的依赖项:
dependencies {
def room_version = "2.2.0-rc01"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// For Kotlin use kapt instead of annotationProcessor
}
以下内容为Kotlin的内容,可以不添加,那样就减少下载库的量,会等的时间更短
----------------------------------------------------------------------------------------------------
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$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"
// Test helpers
testImplementation "androidx.room:room-testing:$room_version"
2.创建实体类 Word
@Entity //进行注解操作,绝对不能少
public class Word {
//这个是设置主键,让他自动生成,自动递增id进行标号
@PrimaryKey(autoGenerate = true)
private int id;
/************************只能英文************************/
//@ColumnInfo以你写的作为记忆,如果你不写的话,他会以你的变量名称word作为记忆
@ColumnInfo(name = "english_word")
private String word;
@ColumnInfo(name = "chinese_meaning")
private String chineseMeaning;
/*************第二步,重写方法,id不用重写,因为他是主键,是自动生成的*********/
public Word(String word, String chineseMeaning) {
this.word = word;
this.chineseMeaning = chineseMeaning;
}
/********************第三步,重写方get,set方法,id可以写**********************/
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public String getChineseMeaning() {
return chineseMeaning;
}
public void setChineseMeaning(String chineseMeaning) {
this.chineseMeaning = chineseMeaning;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
3. 创建抽象类 WordDao (Interface)
//进行注解操作,绝对不能少
@Dao //访问数据库操作的一个接口
//所有数据库的操作都要在里面进行
public interface WordDao {
/*****************************修饰词的意义是,编译的时候会给我们生成代码***************/
@Insert
//允许传递多个数,如果一个的话,他是Word word , 多个的话是Word ...words
void insertWords(Word... words);
@Update
//当你定义int update时,他会给你回复你修改了几个结果
void update(Word... words);
@Delete
void delete(Word... words);
@Query("DELETE FROM WORD")
//这是清空全部
void deletall();
@Query("SELECT*FROM WORD ORDER BY ID DESC")
//降序排列,表示最新的值将放在最前面
List<Word> getall();
}
4. 创建WordDatabase 声明为抽象,并且继承自自己的父类RoomDatabase。(Abstract)
//entity 实体,如果有多个,要用 , 分割开,第二个是版本
@Database(entities = {Word.class},version = 1,exportSchema = false) //进行注解操作,绝对不能少
public abstract class WordDatabase extends RoomDatabase {
//如果有多个Entity 应该写多个Dao
public abstract WordDao getWordDao();
}
5. 进行测试,查看效果
public class MainActivity extends AppCompatActivity {
WordDatabase wordDatabase;
WordDao wordDao;
Button buttoninsert, buttonupdate, buttondelte, buttondelteall;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//第三个第数据库名称
// wordDatabase=
Room.databaseBuilder(this,WordDatabase.class,"shujvkumingcheng").build();
//.allowMainThreadQueries()强制在主线程执行,这个是错误的,应该是上一个语句才是正确,但是因 为为了看效果,所以简单的过一下
wordDatabase = Room.databaseBuilder(this, WordDatabase.class, "shujvkumingcheng").allowMainThreadQueries().build();
wordDao = wordDatabase.getWordDao();
//添加数据
textView = findViewById(R.id.textView);
buttoninsert = findViewById(R.id.buttoninsert);
buttoninsert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Word word1 = new Word("zhang", "张");
Word word2 = new Word("qian", "前");
wordDao.insertWords(word1, word2);
updateView();
}
});
//删除数据
buttondelte = findViewById(R.id.buttondelterone);
buttondelte.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//这里的里面设置什么都行,因为是依靠主键删除
Word word=new Word("1","2");
word.setId(27);
wordDao.delete(word);
updateView();
}
});
buttondelteall = findViewById(R.id.buttondelterAll);
buttondelteall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
wordDao.deletall();
updateView();
}
});
//更新数据
buttonupdate = findViewById(R.id.buttonupdate);
buttonupdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Word word = new Word("aaa", "A");
word.setId(25);
wordDao.delete(word);
updateView();
}
});
updateView();
}
//显示数据集合
void updateView() {
List<Word> list = wordDao.getall();
String text = "";
for (int i = 0; i < list.size(); i++) {
Word word = list.get(i);
text = text + word.getId() + word.getWord() + "----" + word.getChineseMeaning() + "\n";
}
textView.setText(text);
}
}