本是青灯不归客,却因浊酒恋红尘
一,基本使用
关于Room数据库的基本使用,请参考文章Android--Jetpack--数据库Room详解一-CSDN博客
二,Room与ViewModle,LiveData的结合使用
LiveData与ViewModle的使用,请参考文章Android--Jetpack--LiveData-CSDN博客
我们通过结合Room与LiveData和ViewModle的使用,可以使当我们的数据库发生变化的时候,自动的去更新UI。
下面来看一个简单的使用案例:
1,还是 Android--Jetpack--数据库Room详解一-CSDN博客
中创建的数据库,表还是YuanZhen这张表, 我们把YuanZhenDao这个Dao类添加一个新的方法,使得可以查询到LiveData包装的集合:
@Dao
public interface YuanZhenDao {@Insertvoid insert(YuanZhen... yuanzhens);@Deletevoid delete(YuanZhen yuanZhen);@Updatevoid update(YuanZhen yuanZhen);@Query("select * from YuanZhen")List<YuanZhen> getAll();@Query("select * from YuanZhen where name like :name")YuanZhen getByName(String name);@Query("select * from YuanZhen where age in(:ages)")List<YuanZhen> getByAges(int[] ages);@Query("select name,address from YuanZhen ")public List<YuanZhenNew> getNew();@Query("select * from YuanZhen")LiveData<List<YuanZhen>> getAllLiveDataYZ();
}
2,将数据库MyDatabase修改为单例模式:
@Database(entities = {YuanZhen.class},version = 1)
public abstract class MyDatabase extends RoomDatabase {private static MyDatabase instance;public static synchronized MyDatabase getInstance(Context context){if(instance==null){instance= Room.databaseBuilder(context.getApplicationContext(),MyDatabase.class,"YuanZhenDb").build();}return instance;}public abstract YuanZhenDao yuanZhenDao();}
3,创建一个包装类,包装LiveData给ViewModel使用:
public class YuanZhenDecorate {private LiveData<List<YuanZhen>> liveDataAllYZ;private YuanZhenDao yuanZhenDao;public YuanZhenDecorate(Context context) {yuanZhenDao =MyDatabase.getInstance(context).yuanZhenDao();if(liveDataAllYZ==null){liveDataAllYZ=yuanZhenDao.getAllLiveDataYZ();}}void insert(YuanZhen... yuanZhens){yuanZhenDao.insert(yuanZhens);}void delete(YuanZhen yuanZhen){yuanZhenDao.delete(yuanZhen);}void update(YuanZhen yuanZhen){yuanZhenDao.update(yuanZhen);}List<YuanZhen> getAll(){return yuanZhenDao.getAll();}LiveData<List<YuanZhen>> getAllLiveDataYZ(){return yuanZhenDao.getAllLiveDataYZ();}}
4,创建一个viewmodle:
public class YZViewModdel extends AndroidViewModel {private YuanZhenDecorate yuanZhenDecorate;public YZViewModdel(@NonNull Application application) {super(application);yuanZhenDecorate =new YuanZhenDecorate(application);}void insert(YuanZhen... yuanZhens){yuanZhenDecorate.insert(yuanZhens);}void delete(YuanZhen yuanZhen){yuanZhenDecorate.delete(yuanZhen);}void update(YuanZhen yuanZhen){yuanZhenDecorate.update(yuanZhen);}List<YuanZhen> getAll(){return yuanZhenDecorate.getAll();}LiveData<List<YuanZhen>> getAllLiveDataYZ(){return yuanZhenDecorate.getAllLiveDataYZ();}}
5,创建一个recyclerview的adapter:
public class MyAdapter extends RecyclerView.Adapter {private LayoutInflater mLayoutInflater;private List<YuanZhen> mList;public MyAdapter(Context context,List<YuanZhen> mList) {mLayoutInflater =LayoutInflater.from(context);this.mList =mList;}public void setData(List<YuanZhen> mList) {this.mList = mList;}@NonNull@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {return new ViewHolder(mLayoutInflater.inflate(R.layout.item, parent, false));}@Overridepublic void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {((ViewHolder)holder).mTxt.setText(mList.get(position).getName());}@Overridepublic int getItemCount() {if(mList!=null){return mList.size();}return 0;}class ViewHolder extends RecyclerView.ViewHolder {TextView mTxt;public ViewHolder(@NonNull View itemView) {super(itemView);mTxt = (TextView) itemView.findViewById(R.id.txt);}}}
6,activity的xml布局:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_room"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>
7,item的xml布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"><TextViewandroid:id="@+id/txt"android:layout_width="match_parent"android:layout_height="30dp"android:textSize="16sp"/></RelativeLayout>
8,使用:
public class MainActivity extends AppCompatActivity {StudentViewModel studentViewModel;ListView listView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);listView = findViewById(R.id.listView);studentViewModel = ViewModelProviders.of(this).get(StudentViewModel.class);studentViewModel.getAllLiveDataStudent().observe(this, new Observer<List<Student>>() {@Overridepublic void onChanged(List<Student> students) {listView.setAdapter(new GoodsAdapter(MainActivity.this, students));}});for (int i = 0; i < 50; i++) {studentViewModel.insert(new Student("jett", "123", 1));}new Thread() {@Overridepublic void run() {for (int i = 0; i < 50; i++) {try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}studentViewModel.update(new Student(6, "jett" + i, "123", 1));}}}.start();}
}
9,运行:
三,数据库的升级
1,强制升级,执行之后数据库的结构会发生变化,但是数据库的数据会丢失。
这种情况比较适合toB开发,数据库版本高降到低的情况,紧急发一版新的程序给现场升级。
使用 :fallbackToDestructiveMigration()
@Database(entities = {YuanZhen.class},version = 2)
public abstract class MyDatabase extends RoomDatabase {private static MyDatabase instance;public static synchronized MyDatabase getInstance(Context context){if(instance==null){instance= Room.databaseBuilder(context.getApplicationContext(),MyDatabase.class,"YuanZhenDb")//强制升级.fallbackToDestructiveMigration().build();}return instance;}public abstract YuanZhenDao yuanZhenDao();}
2,一般的升级方式
假如我们要增加一个字段price:
@Entity
public class YuanZhen {@PrimaryKey(autoGenerate = true)private int id;@ColumnInfo(name ="name")private String name;@ColumnInfo(name ="age")private int age;@ColumnInfo(name ="address")private String address;@ColumnInfo(name = "price")private int price;@Ignoreprivate String sex;public YuanZhen(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void setId(int id) {this.id = id;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public void setAddress(String address) {this.address = address;}public int getId() {return id;}public String getName() {return name;}public int getAge() {return age;}public String getAddress() {return address;}@Overridepublic String toString() {return "YuanZhen{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", address='" + address + '\'' +", sex='" + sex + '\'' +'}';}
}
在MyDatabase中增加升级功能:
@Database(entities = {YuanZhen.class},version = 2,exportSchema = false)
public abstract class MyDatabase extends RoomDatabase {private static MyDatabase instance;public static synchronized MyDatabase getInstance(Context context){if(instance==null){instance= Room.databaseBuilder(context.getApplicationContext(),MyDatabase.class,"YuanZhenDb")//强制升级// .fallbackToDestructiveMigration().addMigrations(MIGRATION_1_2).build();}return instance;}public abstract YuanZhenDao yuanZhenDao();static final Migration MIGRATION_1_2=new Migration(1,2) {@Overridepublic void migrate(@NonNull SupportSQLiteDatabase database) {//在这里用sql脚本完成数据变化database.execSQL("alter table yuanzhen add column price integer not null default 1");}};}
这里和greendao最大的不同就是,这里需要自己去写升级脚本,虽然增加了工作量,但是也更加灵活了。