Room
SQLite 的抽象
流畅地访问SQLite数据库
数据库操作原则性不能放在主线程(UI线程),因为这样的耗时操作可能导致用户体验迟钝,一般超过10ms,用户就会有明显的感知
原本Android的数据库操作是相对很复杂,利用jetpack中的room组件可以稍微简单点
Entity Dao Database
Entity
一行就是一个Entity, 它定义了整个表的结构
添加依赖
- 创建一个新项目
- 进入gradle
- 按照以下代码添加依赖(为确保版本为最新,最好查看官方文档)
dependencies {
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// optional - RxJava2 support for Room
implementation "androidx.room:room-rxjava2:$room_version"
// optional - RxJava3 support for Room
implementation "androidx.room:room-rxjava3:$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"
// optional - Paging 3 Integration
implementation "androidx.room:room-paging:2.4.0-alpha04"
}
optional选择中如果你是使用java语言,那为了加快项目的构建速度,建议只保存Test helpers这一选项
案例
word 类
这个案例是一个简单的词汇记录案例,每一个单词和其对应的中文意思就相当于一条记录,也就是一个entity,下面是创建好的Word类,和普通的自定义类其实是一样的,只是多了一些专属于Room的注解,然后构造方法和getter setter方法就直接一键生成就好了
@Entity
public class Word {
//这个注解意为将ID作为主键,并且自动生成
@PrimaryKey(autoGenerate = true)
private int ID;
//这个注解意为给这个字段取个名字,如果不注解,那么就会用你定义的对象的名字
@ColumnInfo(name = "english word")
private String word ;
@ColumnInfo(name = "chinese meaning")
private String chineseMeaning;
//下面重写构造方法,然后设置一些getter setter方法
public Word(String word, String chineseMeaning) {
this.word = word;
this.chineseMeaning = chineseMeaning;
}
public int getID() {
return ID;
}
public void setID(int ID) {
this.ID = 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;
}
}
WordDao接口
和最开始讲的一样,WordDao实际上就是一个用来操作数据库的接口,里面你可以自定义一些方法,通过注解的方式,在之后的使用中你也不用重写里面的方法,系统帮你生成。而后面我们也可以直接通过database里面的静态方法直接获取worddao的实现类对象。下面是代码部分
public interface WordDao {
@Insert
void insertWords(Word... words);
@Update
void updataWords(Word... words);
@Delete
void deleteWords(Word... words);
@Query("DELETE FROM WORD")
void deleteAllWords();
//注解里的DESC意为降序,就是最新的会放在前面,该方法返回一个类型为word的list
@Query("SELECT * FROM WORD ORDER BY ID DESC")
List<Word> getAllWords();
}
WordDatabase抽象类
该类继承于RoomDatabase,我们只需要在里面添加一个抽象方法,就是获取wordDao的实现类对象的方法即可
//这里注解括号中第一个意为该数据库每一个entity只包含一个对象,第二个是版本,第三个和数据导出有关系,反正先false
@Database(entities = {Word.class},version =1,exportSchema = false)
public abstract class WordDatabase extends RoomDatabase {
public abstract WordDao getWordDao();
}
mainactivity
在mainactivity中,我们的目标其实很简单
- 创建wordDatabase对象
- 创建wordDao对象
- 把其他一些控件该关联的关联上,把一些小功能该实现的实现
下面看代码
public class MainActivity extends AppCompatActivity {
//这里先把该定义的对象先定义了
WordDatabase wordDatabase;
WordDao wordDao;
Button buttonInsert,buttonUpdata,buttonClear,buttonDelete;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//这里创建wordDatabase,按照固定格式来就好,参数列表第一个是指向这个activity,第二个是WordDatabase的class,第三个是数据库文件名字,然后很关键的一步,我们在.build()之前先调用.allowMainThreadQueries(),主要是为了让下面那些数据库操作能够在主线程执行,当然以后不建议去这么做,现在为了图个方便,不然程序就运行不了。
wordDatabase = Room.databaseBuilder(this,WordDatabase.class,"word_database").allowMainThreadQueries().build();
//这里直接调用静态方法生成wordDao
wordDao = wordDatabase.getWordDao();
//关联控件
buttonInsert.findViewById(R.id.button_insert);
buttonUpdata.findViewById(R.id.button_updata);
buttonClear.findViewById(R.id.button_clear);
buttonDelete.findViewById(R.id.button_delete);
//给其中一个按钮添加功能
buttonInsert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Word word = new Word("Hello","你好");
Word word2 = new Word("world","世界");
wordDao.insertWords(word,word2);
updataView();
}
});
}
//这里我们定义一个方法,用来刷新在屏幕上显示的记录
void updataView(){
List<Word> list = wordDao.getAllWords();
String str = "";
for (int i = 0; i < list.size(); i++) {
Word word = list.get(i);
str += word.getID()+word.getWord()+"="+word.getChineseMeaning()+"\n";
}
textView.setText(str);
}
}