Room数据库和GreenDao使用都差不多,定义的实体类都是用的注解方式。如果项目里面使用了GreenDao,没有必要去迁移Room.好处就是支持同为Android Architecture Component的LiveData,实现数据的动态刷新和绑定组件生命周期功能。根据项目而定吧,性能方面也差不多。属于jetpack,就顺带着学习一下。官网全是kotlin表达的。
设想一个场景,一个activity,加载一个recycleView,数据源每次初始化的时候,从服务器拿到都是一样的数据,如果有个需求,后台每次就给你11个工人的信息,信息包含了姓名,工牌,是否吃饭。我们要记录他到底有没有吃饭,这样用sp就比较复杂了。只能是把他们一个个状态保存在本地。这样跟状态栏搜索历史很像,卸载了就没有了,卸载了还有的话只能说这种是拉取得后台,今天只讲状态保存在本地。
添加依赖
//Room数据库
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
实体Bean,代表工人的所有属性
可以理解为数据源的bean类型
public class Person{
public Person(String name, int id, boolean eatrice){
this.name = name;
this.id = id;
this.eatrice = eatrice;
}
String name;
int id;
boolean eatrice;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public boolean isEatrice(){
return eatrice;
}
public void setEatrice(boolean eatrice){
this.eatrice = eatrice;
}
@Override
public String toString(){
return "Person{" + "name='" + name + '\'' + ", id=" + id + ", eatrice=" + eatrice + '}';
}
}
新建AppDataBase
以后任何新建的其他表单只需要在这里里面配置一下就OK了,包括entities里面和方法那一块
PersonStateDao personStateDao = AppDataBase.getInstance().getPersonStateDao();就是拿到PersionStateDao的表单,然后进一步进行操作,也就是说,如果有多个表单,都需要在这里配置,拿任何一个表单都需要AppDataBase.getInstance().xxxx
//需要用到哪些表单,一定要.class,否则加载不到
@Database(entities = {PersonStateBean.class}, version = 1)
public abstract class AppDataBase extends RoomDatabase{
private static AppDataBase instance;
private static final String DBName = "testRoom";
//拿到对应的表单对象,这个表单内部的方法是供你条件查询或者其他处理的,如果有其他的表,一样要在这里添加
public abstract PersonStateDao getPersonStateDao();
public static AppDataBase getInstance() {
if (instance == null) {
synchronized (AppDataBase.class) {
if (instance == null) {
instance = createDB();
}
}
}
return instance;
}
private static AppDataBase createDB(){
return Room.databaseBuilder(ContextProvider.get().getContext(), AppDataBase.class, DBName + ".db").addCallback(new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
Log.d("AppDataBase", "oncreat");
}
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
Log.d("AppDataBase", "onOpen");
}
}).addMigrations(MIGRATION_1_2).addMigrations(MIGRATION_2_1).allowMainThreadQueries().build();
}
static Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("DROP TABLE IF EXISTS LessonVerBean");
database.execSQL("CREATE TABLE IF NOT EXISTS LessonVerBean(" +
"id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
"lesson_id INTEGER NOT NULL" +
",version INTEGER NOT NULL,type INTEGER NOT NULL)");
}
};
static Migration MIGRATION_2_1 = new Migration(2, 1) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("DROP TABLE IF EXISTS LessonVerBean");
}
};
}
新建表格式属性PersonStateBean
你想记录工人的部分属性,比如工号,是否吃饭的状态,他们还有一个共同属性是人(后期为了拿到所有工人表),注意这里不是数据源的属性,这里的属性由你定,根据业务,能快速查询,比如根据id查对应的人,全部吃过饭的工人的数目,当然,这里也可以加个name属性,但是这里的业务不需要。
@Entity
public class PersonStateBean{
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "person_id")
public int personId;
@ColumnInfo(name = "is_eat")
public boolean isEat;
@ColumnInfo(name = "type")
public int type;
}
新建表单PersonStateDao(这里面真正可以进行增删改查的具体操作)
@Dao
public interface PersonStateDao extends BaseDao<PersonStateBean>{
//根据id精确查找某一个persion
@Query("select *from personstatebean where person_id=(:personId)")
PersonStateBean queryPersonById(int personId);
//把吃了饭的人全部找出来
@Query("select * from personstatebean where is_eat=(:isEat)")
PersonStateBean queryListPersonByEat(boolean isEat);
//把所有人找出来(他们的共有属性,是自己定的type=1)
@Query("select * from personstatebean where type=(:type)")
List<PersonStateBean> queryListPersonByType(int type);
}
BaseDao是提供的公有父类,封装了增加删除功能,如果表对象有冲突直接替换的功能。
@Dao
public interface BaseDao<T> {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(T item);
@Insert
void insertItems(List<T> items);
@Delete
void delete(T item);
@Delete
void deleteItems(T items);
}
直接在Activity调用
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private List<Person> list=new ArrayList<>();;
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycleview);
LinearLayoutManager linearLayoutManage = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManage);
adapter = new MyAdapter(list, this);
initData();
recyclerView.setAdapter(adapter);
initListener();
}
private void initListener(){
adapter.setListener(new MyAdapter.AdapterListener(){
@Override
public void onclick(int position){
boolean eatrice =list.get(position).isEatrice();
eatrice = !eatrice;
list.get(position).setEatrice(eatrice);
adapter.notifyDataSetChanged();
//改变数据库
Person person = list.get(position);
int id = person.getId();
PersonStateBean personStateBean = personStateDao.queryPersonById(id);
if(null!=personStateBean){
personStateBean.isEat=eatrice;
personStateDao.insert(personStateBean);
}
}
});
}
//查询数据库,数据库有数据沿用数据库,如果没有代表第一次进入用初始化的数据
PersonStateDao personStateDao = AppDataBase.getInstance().getPersonStateDao();
private void initData(){
getServerData();
//这里所有person在表里面有的共有属性都是1,区分是不是第一次进来
List<PersonStateBean> listPersonStateBean = personStateDao.queryListPersonByType(1);
if(null == listPersonStateBean||listPersonStateBean.size()==0){
for(int i = 0; i < list.size(); i++){
PersonStateBean personStateBean = new PersonStateBean();
personStateBean.isEat = false;
personStateBean.personId = list.get(i).getId();
personStateBean.type = 1;
personStateDao.insert(personStateBean);
}
}else{
for(int i = 0; i < list.size(); i++){
Person person = list.get(i);
PersonStateBean personStateBean = personStateDao.queryPersonById(person.getId());
if(personStateBean != null){
//杀掉程序后,沿用以数据库当初存的为准,服务器不愿意改状态
boolean isEat = personStateBean.isEat;
list.get(i).setEatrice(isEat);
}
}
}
adapter.notifyDataSetChanged();//数据库取出来刷新
}
//第一次请求的时候,服务器使用就给你这些固定的数据,本地保存数据把,卸载之后就没有,可以用做搜索历史
private void getServerData(){
list.add(new Person("张三", 1, false));
list.add(new Person("李四", 2, false));
list.add(new Person("王五", 3, false));
list.add(new Person("哈哈1", 4, false));
list.add(new Person("哈哈2", 5, false));
list.add(new Person("哈哈3", 6, false));
list.add(new Person("哈哈4", 7, false));
list.add(new Person("哈哈5", 8, false));
list.add(new Person("哈哈6", 9, false));
list.add(new Person("哈哈7", 10, false));
list.add(new Person("哈哈8", 11, false));
}
监听器刷新
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
List<Person>list;
Context context;
public MyAdapter(List<Person> list, Context context){
this.list = list;
this.context = context;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
View view= LayoutInflater.from(context).inflate(R.layout.item_persion,parent,false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, final int position){
holder.tv_name.setText(list.get(position).getName());
holder.tv_id.setText("工牌:"+list.get(position).getId());
holder.tv_iseat.setText(list.get(position).isEatrice()?"吃饭了":"没吃饭");
holder.itemView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if(adapterListener!=null){
adapterListener.onclick(position);
}
}
});
}
@Override
public int getItemCount(){
return list.size();
}
AdapterListener adapterListener;
public void setListener(AdapterListener listener){
adapterListener=listener;
}
public interface AdapterListener{
void onclick(int position);
}
public class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_name;
TextView tv_id;
TextView tv_iseat;
public MyViewHolder(@NonNull View itemView){
super(itemView);
tv_name=itemView.findViewById(R.id.tv_name);
tv_id=itemView.findViewById(R.id.tv_id);
tv_iseat=itemView.findViewById(R.id.tv_iseat);
}
}
}
github地址:https://github.com/283006603/room 有什么问题可以QQ问我的。