安卓开发-利用Room简化数据库操作
前言:
书籍:《Android Studio从零基础到APP上线》
本文是对改书中例子进行小幅度改动,符合本人在开发过程中的要求,并且操作运行成功
附上界面代码和全部操作。
界面画面
界面代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/Addproducts_name"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_name"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="@string/Addproducts_name_edit"
android:inputType="text"
android:maxLength="12"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/Addproducts_ID"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_id"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_id"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="@string/Addproducts_ID_edit"
android:inputType="text"
android:maxLength="20"
android:textColor="@color/black"
android:textSize="17sp" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_toRightOf="@id/et_id"
android:background="@drawable/id"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/Addproducts_price"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_price"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_price"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="@string/Addproducts_price_edit"
android:inputType="text"
android:maxLength="12"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_date"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/Addproducts_date"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_date"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="@string/Addproducts_date_edit"
android:inputType="text"
android:maxLength="12"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/Addproducts_count"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/et_count"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:layout_toRightOf="@+id/tv_count"
android:background="@drawable/editext_selector"
android:gravity="left|center"
android:hint="@string/Addproducts_count_edit"
android:inputType="text"
android:maxLength="12"
android:textColor="@color/black"
android:textSize="17sp" />
</RelativeLayout>
<TextView
android:id="@+id/tv_notes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/notes"
android:textColor="@color/black"
android:textSize="17sp" />
<EditText
android:id="@+id/myEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/editext_selector"
android:inputType="textMultiLine"
android:lines="10"
android:textColor="@color/black" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/btn_save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/submit"/>
</LinearLayout>
界面逻辑代码
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import com.example.myapplication.Utils.ToastUtil;
import com.example.myapplication.dao.BookDao;
import com.example.myapplication.dao.MainApplication;
import com.example.myapplication.entity.BookInfo;
import com.example.myapplication.dao.BookDatabase;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private EditText et_name;
private EditText et_id;
private EditText et_price;
private EditText et_date;
private EditText et_count;
private EditText myEditText;
private BookDao bookDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = findViewById(R.id.et_name);
et_id = findViewById(R.id.et_id);
et_price = findViewById(R.id.et_price);
et_date = findViewById(R.id.et_price);
et_count = findViewById(R.id.et_count);
myEditText = findViewById(R.id.myEditText);
findViewById(R.id.btn_save).setOnClickListener(this);
bookDao = MainApplication.getInstance().getBookDB().bookDao();
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_save){
String name = et_name.getText().toString();
String id = et_id.getText().toString();
String price = et_price.getText().toString();
String date = et_date.getText().toString();
String count = et_count.getText().toString();
String myText = myEditText.getText().toString();
if (TextUtils.isEmpty(name)){
ToastUtil.show(this, "请先填写商品名称");
return;
}else if (TextUtils.isEmpty(id)){
ToastUtil.show(this,"请填写商品的ID");
return;
}else if (TextUtils.isEmpty(price)){
ToastUtil.show(this,"请填写商品的价格");
return;
}else if (TextUtils.isEmpty(date)){
ToastUtil.show(this,"请填写商品的入库日期");
return;
}else if (TextUtils.isEmpty(count)){
ToastUtil.show(this,"请填写商品的入库数量");
return;
}else if (TextUtils.isEmpty(myText)){
ToastUtil.show(this,"请填写商品的备注");
return;
}
BookInfo info = new BookInfo();
info.setName(name);
info.setIid(id);
info.setPrice(price);
info.setDate(date);
info.setCount(count);
info.setMyEditText(myText);
bookDao.insertOneBook(info);
ToastUtil.show(this,"数据已写入Room数据库");
}
}
}
1.应用组件APPlication
打开组AndroidManifest.xml,给application节点加上name属性,表示application的入口代码是MainApplication.java.修改后的代码如下:
<application
android:allowBackup="true"
android:name=".MainApplication"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
2.创建MainApplication.java
在Java代码的包名下目录下创建MainApplication.java,要求该类继承Application,继承之后重写方法
onCreate、onTerminate
代码如下:
package com.example.myapplication;
import static androidx.constraintlayout.helper.widget.MotionEffect.TAG;
import android.app.Application;
import android.nfc.Tag;
import android.util.Log;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import com.example.myapplication.BookDatabase;
import java.util.HashMap;
public class MainApplication extends Application {
private final static String TAG = "MainApplication";
private static MainApplication mApp; // 声明一个当前应用的静态实例
// 声明一个公共的信息映射对象,可当作全局变量使用
public HashMap<String, String> infoMap = new HashMap<String, String>();
public static int goodsCount = 0;
private BookDatabase bookDatabase; // 声明一个书籍数据库对象
public static MainApplication getInstance(){
return mApp;
}
@Override
public void onCreate(){
super.onCreate();
Log.d(TAG,"oncreate");
mApp = this;
bookDatabase = Room.databaseBuilder(mApp,BookDatabase.class,"BookInfo")
.addMigrations()
.allowMainThreadQueries()
.build();
}
public BookDatabase getBookDB(){
return bookDatabase;
}
@Override
public void onTerminate() {
super.onTerminate();
Log.d(TAG, "onTerminate");
}
}
3.开始Room简化数据库操作
3.1导包
在模块级别的build.gradle/dependencies节点下方增加如下代码
implementation 'androidx.room:room-runtime:2.5.2'
annotationProcessor 'androidx.room:room-compiler:2.5.2'
3.2编写的对应实体类
并编写相应的get/set方法
package com.example.myapplication;
import androidx.annotation.NonNull;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity
public class BookInfo {
private String name;//商品名称
@PrimaryKey
@NonNull
private String iid; //商品条码
private String price;//商品价格
private String date;//商品入库时间
private String count;//商品入库数量
private String myEditText;//商品的备注
public String getName() {
return name;
}
public String getIid() {
return iid;
}
public String getPrice() {
return price;
}
public String getDate() {
return date;
}
public String getCount() {
return count;
}
public String getMyEditText() {
return myEditText;
}
public void setName(String name) {
this.name = name;
}
public void setIid(String iid) {
this.iid = iid;
}
public void setPrice(String price) {
this.price = price;
}
public void setDate(String date) {
this.date = date;
}
public void setCount(String count) {
this.count = count;
}
public void setMyEditText(String myEditText) {
this.myEditText = myEditText;
}
}
3.3编写对应的持久化类
作用:将数据保存到磁盘,其实等同于增删改的SQL语句,如类名是BookDao,那么该类必须加@Dao注解,其他的数据库操作也要加注解,代码如下:
package com.example.myapplication;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.example.myapplication.BookInfo;
import java.util.List;
@Dao
public interface BookDao {
@Query("SELECT * FROM BookInfo") // 设置查询语句
List<BookInfo> queryAllBook(); // 加载所有书籍信息
@Query("SELECT * FROM BookInfo WHERE name = :name") // 设置带条件的查询语句
BookInfo queryBookByName(String name); // 根据名字加载书籍
@Insert(onConflict = OnConflictStrategy.REPLACE) // 记录重复时替换原记录
void insertOneBook(BookInfo book); // 插入一条书籍信息
@Insert
void insertBookList(List<BookInfo> bookList); // 插入多条书籍信息
@Update(onConflict = OnConflictStrategy.REPLACE)// 出现重复记录时替换原记录
int updateBook(BookInfo book); // 更新书籍信息
@Delete
void deleteBook(BookInfo book); // 删除书籍信息
@Query("DELETE FROM BookInfo WHERE 1=1") // 设置删除语句
void deleteAllBook(); // 删除所有书籍信息
}
3.4编写对应的数据库类
这个默认的数据库要从Roomdatabase派生而来,并添加@Database注解。
代码如下:
package com.example.myapplication;
import androidx.room.Database;
import androidx.room.RoomDatabase;
import com.example.myapplication.BookInfo;
import com.example.myapplication.BookDao;
@Database(entities = {BookInfo.class},version = 1,exportSchema = false)
public abstract class BookDatabase extends RoomDatabase {
public abstract BookDao bookDao();
}
3.5声明数据库唯一实例
为了避免重复打开数据库造成内存泄漏问题,,每个数据实例在APP运行过程中理应只有一个实例,将此实例定义为单例模式,
代码见小节 2.创建MainApplication.java
3.6在操作界面获取数据库表的持久化对象
bookDao = MainApplication.getInstance().getBookDB().bookDao();
全部代码如下:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import com.example.myapplication.BookInfo;
public class Addproducts extends AppCompatActivity implements View.OnClickListener {
private EditText et_name;
private EditText et_id;
private EditText et_price;
private EditText et_date;
private EditText et_count;
private EditText myEditText;
private BookDao bookDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addproducts);
et_name = findViewById(R.id.et_name);
et_id = findViewById(R.id.et_id);
et_price = findViewById(R.id.et_price);
et_date = findViewById(R.id.et_price);
et_count = findViewById(R.id.et_count);
myEditText = findViewById(R.id.myEditText);
findViewById(R.id.btn_save).setOnClickListener(this);
bookDao = MainApplication.getInstance().getBookDB().bookDao();
}
@Override
public void onClick(View v){
if (v.getId() == R.id.btn_save){
String name = et_name.getText().toString();
String id = et_id.getText().toString();
String price = et_price.getText().toString();
String date = et_date.getText().toString();
String count = et_count.getText().toString();
String myText = myEditText.getText().toString();
if (TextUtils.isEmpty(name)){
ToastUtil.show(this, "请先填写商品名称");
return;
}else if (TextUtils.isEmpty(id)){
ToastUtil.show(this,"请填写商品的ID");
return;
}else if (TextUtils.isEmpty(price)){
ToastUtil.show(this,"请填写商品的价格");
return;
}else if (TextUtils.isEmpty(date)){
ToastUtil.show(this,"请填写商品的入库日期");
return;
}else if (TextUtils.isEmpty(count)){
ToastUtil.show(this,"请填写商品的入库数量");
return;
}else if (TextUtils.isEmpty(myText)){
ToastUtil.show(this,"请填写商品的备注");
return;
}
BookInfo info = new BookInfo();
info.setName(name);
info.setIid(id);
info.setPrice(price);
info.setDate(date);
info.setCount(count);
info.setMyEditText(myText);
bookDao.insertOneBook(info);
ToastUtil.show(this,"数据已写入Room数据库");
}
}
}
ToastUtil.show(this,"请填写商品的入库数量");
return;
}else if (TextUtils.isEmpty(myText)){
ToastUtil.show(this,"请填写商品的备注");
return;
}
BookInfo info = new BookInfo();
info.setName(name);
info.setIid(id);
info.setPrice(price);
info.setDate(date);
info.setCount(count);
info.setMyEditText(myText);
bookDao.insertOneBook(info);
ToastUtil.show(this,"数据已写入Room数据库");
}
}
}