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