Jetpack---Room数据库

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问我的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342