Android 开发入门(5)
0x07 数据存储
(1)共享参数 SharedPreferences
a. 用法
-
用法
- SharedPreferences 是 Android 的一个轻量级存储工具,采用的存储结构为键值对的方式
- 共享参数的存储介质是符合 XML 规范的配置文件,路径为
/data/data/com.example.test/shared_prefs/xxx.xml
-
使用场景
- 简单且孤立的数据
- 文本形式的数据
- 需要持久化存储的数据
共享参数经常存储的数据包括 App 的个性化数据、用户的行为信息、临时需要保存的片段信息
举例:登记个人信息
-
// import ... import android.content.Context; import android.content.SharedPreferences; import android.view.View; import android.widget.EditText; public class Activity1 extends AppCompatActivity implements View.OnClickListener { private EditText et_name; private EditText et_age; private SharedPreferences preferences; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_1); et_name = findViewById(R.id.et_name); et_age = findViewById(R.id.et_age); findViewById(R.id.btn).setOnClickListener(this); preferences = getSharedPreferences("preference", Context.MODE_PRIVATE); reload(); } private void reload() { // 加载已经存储的信息 String name = preferences.getString("name", null); if (name != null) { et_name.setText(name); } int age = preferences.getInt("age", 0); if (age != 0) { et_age.setText(String.valueOf(age)); } } @Override public void onClick(View view) { String name = et_name.getText().toString(); String age = et_age.getText().toString(); SharedPreferences.Editor editor = preferences.edit(); // 添加信息 editor.putString("name", name); editor.putInt("age", Integer.parseInt(age)); // 提交信息 editor.commit(); } }
b. 实现记住密码功能
(2)数据库 SQLite
a. SQLite 基础语法
-
数据定义
-
创建表格
CREATE TABLE IF NOT EXISTS user_info ( _id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name VARCHAR NOT NULL, age INTEGER NOT NULL );
- 仅单引号包括起来的内容区分大小写
- 通过
IF NOT EXISTS
语句避免重复建表 - SQLite 支持整形
INTEGER
、长整型LONG
、字符串VARCHAR
、浮点数FLOAT
,不支持布尔类型,如果直接保存布尔数据会被强转为 0 / 1,分别代表 false/true - 建表必须有唯一标识字段(主键):
_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL
-
删除表格
DROP TABLE IF EXISTS user_info;
-
修改表结构
SQLite 只支持增加字段,不支持修改/删除字段,且每次智能添加一列字段
ALTER TABLE user_info ADD COLUMN age INTEGER;
-
-
数据操纵语言
-
添加
INSERT INTO user_info (name, age) VALUES ('张三', 20);
-
删除
DELETE FROM user_info WHERE name='张三'
-
修改
UPDATE user_info SET age=21 WHERE name
-
查询
SELECT name FROM table WHERE name='张三'
-
排序输出结果
SELECT * FROM user_info ORDER BY age ASC;
- ASC:升序
- DESC:降序
-
-
b. 数据库管理器 SQLiteDatabase
-
SQLiteDatabase 是 SQLite 的数据库管理类,提供了若干操作数据表的 API,包含以下三个类
-
数据处理类,用于数据表层面的操作
execSQL()
:执行拼接好的 SQL 控制语句insert()
:插入一条记录update()
:更新符合条件的记录delete()
:删除符合条件的记录query()
:执行查询操作,返回结果集的游标rawQuery()
:执行拼接好的 SQL 查询语句,返回结果集的游标
使用详情见UserDBHelper
-
事务类,用于事务层面的操作
beginTransaction()
:开始事务setTransactionSuccessful()
:设置事务的成功标志endTransaction()
:结束事务
以数据处理类中的
insert()
方法实现为例:ContentValues values = new ContentValues(); values.put("name", user.name); values.put("age", user.age); try { mWDB.beginTransaction(); mWDB.insert(TABLE_NAME, null, values); // 第一条记录 mWDB.insert(TABLE_NAME, null, values); // 第二条记录 mWDB.setTransactionSuccessful(); } catch (Exception e) { e.printStackTrace(); } finally { mWDB.endTransaction(); } return 1;
当两条记录添加之间出现错误(如:
int i = 1 / 0
)时,通过添加事务的方法,避免出现仅成功添加第一条记录。事务若未成功,则通过回滚的措施取消本次添加操作 -
管理类,用于数据库层面的操作
openDatabase()
:打开指定路径的数据库isOpen()
:判断数据库是否已打开close()
:关闭数据库getVersion()
:获取数据库版本号setVersion()
:设置数据库版本号
通过修改UserDBHelper中的
onUpgrade()
方法// ... private static final int DB_VERSION = 2; // 数据库版本 // ... @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { String sql = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN c1 VARCHAR;"; db.execSQL(sql); sql = "ALTER TABLE " + TABLE_NAME + " ADD COLUMN c2 VARCHAR;"; db.execSQL(sql); }
-
-
创建/打开数据库
SQLiteDatabase db = openOrCreateDatabase(getFilesDir() + "/test.db", Context.MODE_PRIVATE, null); String str = String.format("数据库%s创建%s", db.getPath(), (db != null)?"成功":"失败"); tv.setText(str);
-
删除数据库
deleteDatabase(getFilesDir() + "/test.db");
c. 数据库帮助器 SQLiteOpenHelper
- SQLitOpenHelper 是 Android 提供的数据库辅助工具,用于指导合理使用 SQLite,使用方法:
- 新建一个继承自 SQLiteOpenHelper 的数据库操作类,提示重写
onCreate()
和onUpgrade()
- 封装保证数据库安全的必要方法
- 提供对表记录进行增删改查的操作方法
- 新建一个继承自 SQLiteOpenHelper 的数据库操作类,提示重写
- 游标
- 调用 SQLiteDatabase 的
query()
和rawQuery()
方法时,返回的都是 Cursor 对象,获取查询结果需要根据游标的指示遍历结果集合,包含以下三个类:- 游标控制类,用于指定游标的状态
close()
:关闭游标isClosed()
:判断游标是否关闭isFirst()
:判断游标是否在开头isLast()
:判断游标是否在末尾
- 游标移动类,用于包游标移动到指定位置
move()
:往后移动若干条记录moveToFirst()
:移动游标到开头moveToLast()
:移动游标到末尾moveToNext()
:移动游标到下一条记录moveToPrevious()
:移动游标到上一条记录moveToPosition()
:移动游标到指定位置的记录
- 获取记录类,用于获取记录的数量、类型、取值
getCount()
:获取记录数量getInt()
:获取指定字段整型值getLong()
:获取指定字段长整型值getFloat()
:获取指定字段浮点数值getString()
:获取指定字段的字符串值getType()
:获取指定字段的字段类型
- 游标控制类,用于指定游标的状态
- 调用 SQLiteDatabase 的
举例:人员信息表的增删改查
-
/database/UserDBHelper.java
帮助器,包含 SQLite 操作语句与方法
package com.example.test.database; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.example.test.util.User; import java.util.ArrayList; import java.util.List; public class UserDBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "user.db"; // 数据库名 private static final String TABLE_NAME = "user_info"; // 表名 private static final int DB_VERSION = 1; // 数据库版本 private static UserDBHelper mHelper = null; //帮助器 private SQLiteDatabase mRDB = null; // 读取数据库 private SQLiteDatabase mWDB = null; // 写入数据库 private UserDBHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } // 打开数据库读取连接 public SQLiteDatabase openReadLink() { if (mRDB == null || !mRDB.isOpen()) { mRDB = mHelper.getReadableDatabase(); } return mRDB; } // 打开数据库写入连接 public SQLiteDatabase openWriteLink() { if (mWDB == null || !mWDB.isOpen()) { mWDB = mHelper.getWritableDatabase(); } return mWDB; } // 关闭数据库连接 public void closeLink() { if (mRDB != null && mRDB.isOpen()) { mRDB.close(); mRDB = null; } if (mWDB != null && mWDB.isOpen()) { mWDB.close(); mWDB = null; } } // 利用单例模式获取数据库帮助器的唯一实例 public static UserDBHelper getInstance(Context context) { if (mHelper == null) { mHelper = new UserDBHelper(context); } return mHelper; } // 数据库创建 @Override public void onCreate(SQLiteDatabase db) { String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + " name VARCHAR NOT NULL," + " age INTEGER NOT NULL);"; db.execSQL(sql); } // 数据库版本更新 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } // 增加 public long insert(User user) { ContentValues values = new ContentValues(); values.put("name", user.name); values.put("age", user.age); return mWDB.insert(TABLE_NAME, null, values); } // 删除 public long delete(String name) { return mWDB.delete(TABLE_NAME, "name=?", new String[]{ name }); } // 清空 public long deleteAll() { return mWDB.delete(TABLE_NAME, "1=1", null); } // 修改 public long update(User user) { ContentValues values = new ContentValues(); values.put("name", user.name); values.put("age", user.age); return mWDB.update(TABLE_NAME, values, "name=?", new String[]{ user.name }); } // 查询 public List<User> query(String name) { List<User> list = new ArrayList<>(); // 执行记录查询行为,返回为结果集的游标 Cursor cursor = mRDB.query(TABLE_NAME, null, "name=?", new String[]{ name }, null, null, null); // 循环取出游标指向的每条记录 while (cursor.moveToNext()) { User user = new User(); user.id = cursor.getInt(0); user.name = cursor.getString(1); user.age = cursor.getInt(2); list.add(user); } return list; } // 列出全部 public List<User> queryAll() { List<User> list = new ArrayList<>(); Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null); while (cursor.moveToNext()) { User user = new User(); user.id = cursor.getInt(0); user.name = cursor.getString(1); user.age = cursor.getInt(2); list.add(user); } return list; } }
-
/util/User.java
人员信息类
package com.example.test.util; public class User { public int id; // 序号 public String name; // 姓名 public int age; // 年龄 public User() {} public User(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}'; } }
-
/util/ToastUtil.java
消息提示
package com.example.test.util; import android.content.Context; import android.widget.Toast; public class ToastUtil { public static void show(Context ctx, String desc) { Toast.makeText(ctx, desc, Toast.LENGTH_SHORT).show(); } }
-
MainActivity.java
主活动
package com.example.test; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.TextView; import com.example.test.database.UserDBHelper; import com.example.test.util.ToastUtil; import com.example.test.util.User; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText et_name; private EditText et_age; private TextView tv; UserDBHelper mHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et_name = findViewById(R.id.et_name); et_age = findViewById(R.id.et_age); tv = findViewById(R.id.tv); findViewById(R.id.btn_ins).setOnClickListener(this); findViewById(R.id.btn_del).setOnClickListener(this); findViewById(R.id.btn_upd).setOnClickListener(this); findViewById(R.id.btn_sel).setOnClickListener(this); findViewById(R.id.btn_sal).setOnClickListener(this); findViewById(R.id.btn_dal).setOnClickListener(this); } @Override protected void onStart() { super.onStart(); // 获取数据库帮助器实例 mHelper = UserDBHelper.getInstance(this); mHelper.openReadLink(); mHelper.openWriteLink(); } @Override protected void onStop() { super.onStop(); mHelper.closeLink(); } @Override public void onClick(View view) { String name = et_name.getText().toString(); String age = et_age.getText().toString(); User user = null; switch (view.getId()) { case R.id.btn_ins: user = new User(name, Integer.parseInt(age)); if (mHelper.insert(user) > 0) { ToastUtil.show(this, "添加成功"); } break; case R.id.btn_del: if (mHelper.delete(name) > 0) { ToastUtil.show(this, "删除成功"); } break; case R.id.btn_upd: user = new User(name, Integer.parseInt(age)); if (mHelper.update(user) > 0) { ToastUtil.show(this, "更新成功"); } break; case R.id.btn_sel: String str1 = ""; List<User> list1 = mHelper.query(name); for (User u : list1) { str1 = str1 + u.toString() + "\n"; } tv.setText(str1); break; case R.id.btn_sal: String str2 = ""; List<User> list2 = mHelper.queryAll(); for (User u : list2) { str2 = str2 + u.toString() + "\n"; } tv.setText(str2); break; case R.id.btn_dal: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("警告"); builder.setMessage("确认清空?"); builder.setPositiveButton("确认", (dialogInterface, i) -> { if (mHelper.deleteAll() > 0) { ToastUtil.show(this, "全部清空"); } }); builder.setNegativeButton("取消", (dialogInterface, i) -> {}); AlertDialog alertDialog = builder.create(); alertDialog.show(); break; } return; } }
(3)存储卡的文件操作
a. 私有存储空间与公共存储空间
- 存储空间:Android 把外部存储分成了两部分:
- 仅应用本身可以访问的私有空间
- 所有应用都可以访问的公共空间
- 获取外部存储空间(存储卡)的路径:
- 公共空间:Environment 类的
getExternalStoragePublicDirectory()
方法 - 私有空间:Environment 类的
getExternalFilesDir()
方法
- 公共空间:Environment 类的
b. 在存储卡上读写文本文件
-
读取
-
/util/FileUtil.java
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; // ... public static String openText(String path) { BufferedReader is = null; StringBuilder sb = new StringBuilder(); try { is = new BufferedReader(new FileReader(path)); String line = null; while ((line = is.readLine()) != null) { sb.append(line); } } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); }
-
MainActivity.java
StringBuilder sb = new StringBuilder(); sb.append("姓名:").append(name); sb.append("年龄:").append(age); String fileName = System.currentTimeMillis() + ".txt"; String directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(); path = directory + File.separatorChar + fileName; // String 类型全局变量 FileUtil.saveText(path, sb.toString()); ToastUtil.show(this, "保存成功"); // 消息提示
-
外部存储的私有空间
directory = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString();
-
外部存储的公共空间
directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();
// AndroidManifest.xml // 开启读写权限 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-
内部存储的私有空间
directory = getFilesDir().toString();
-
-
-
写入
-
/util/FileUtil.java
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; // ... public static void saveText(String path, String text) { // path:路径, text:文本内容 BufferedWriter os = null; try { os = new BufferedWriter(new FileWriter(path)); os.write(text); } catch (Exception e) { e.printStackTrace(); } finally { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
MainActivity.java
tv.setText(FileUtil.openText(path));
-
c. 在存储卡上读写图片文件
- Android 的位图工具是 Bitmap,App 读写 Bitmap 可以使用性能更好的 BufferedOutputStream 和 BufferedInputStream
- Android 提供了 BitmapFactory 工具来读取各种来源的图片
decodeResource()
:从资源文件中读取图片信息decodeFile()
:将指定路径的图片读取到 Bitmap 对象decodeStream()
:从输入流读取位图数据
-
读取
-
/util/FileUtil.java
public static Bitmap openImage(String path) { Bitmap bitmap = null; FileInputStream fis = null; try { fis = new FileInputStream(path); bitmap = BitmapFactory.decodeStream(fis); } catch (Exception e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } return bitmap; }
-
MainActivity.java
-
Bitmap bitmap1 = FileUtil.openImage(path); iv.setImageBitmap(bitmap1);
-
Bitmap bitmap1 = BitmapFactory.decodeFile(path); iv.setImageBitmap(bitmap1);
-
iv.setImageURI(Uri.parse(path));
-
-
-
写入
-
/util/FileUtil.java
import android.graphics.Bitmap; // ... public static void saveImage(String path, Bitmap bitmap) { FileOutputStream fos = null; try { fos = new FileOutputStream(path); // 把位图数据压缩到文件输出流中 bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); } catch (Exception e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
MainActivity.java
String fileName = System.currentTimeMillis() + ".jpeg"; // 获取当前 App 的私有下载目录 path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString() + fileName; // 从指定的资源文件(./res/drawable/test.jpg)获取位图对象 Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.test); // 把位图对象保存为图片文件 FileUtil.saveImage(path, bitmap1); ToastUtil.show(this, "保存成功");
-
(4)应用组件 Application
a. 生命周期
-
Application 是 Android 的一大组件,在 App 运行时有且仅有一个 Application 对象贯穿整个生命周期
-
Application 先于 MainActivity 创建
public class MyApplication extends Application { // App 启动时调用 @Override public void onCreate() { super.onCreate(); Log.d("SRIGT", "MyApplication onCreate"); } // App 终止时调用 @Override public void onTerminate() { super.onTerminate(); Log.d("SRIGT", "onTerminate"); } // 配置改变时调用 @Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.d("SRIGT", "onConfigurationChanged"); } }
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d("SRIGT", "MainActivity onCreate"); } }
<application android:name=".util.MyApplication"> <activity android:name=".MainActivity" android:exported="true"> </activity> </application>
运行后,Logcat 的输出结果为:
D/SRIGT: MyApplication onCreate D/SRIGT: MainActivity onCreate
b. 利用 Application 操作全局变量
-
全局的意思是其他代码都可以引用该变量,因此,全局变量是共享数据和消息传递的好帮手
-
适合在 Application 中保存的全局变量主要有下面 3 类数据:
- 会频繁读取的信息,如用户名、手机号等
- 不方便由意图传递的数据,如位图对象、非字符串类型的集合对象等
- 容易因频繁分配内存而导致内存泄露的对象,如 Handle 对象
// MyApplication.java private static MyApplication mApp; // 声明一个公共的信息映射对象,可当作全局变量使用 public HashMap<String, String> infoMap = new HashMap<>(); public static MyApplication getInstance() { return mApp; } // 实例化 mApp @Override public void onCreate() { super.onCreate(); mApp = this; }
// MainActivity.java public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText et; private MyApplication app = MyApplication.getInstance(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et = findViewById(R.id.et); findViewById(R.id.btn).setOnClickListener(this); app = MyApplication.getInstance(); reload(); } private void reload() { String text = app.infoMap.get("Text"); et.setText(text); } @Override public void onClick(View view) { String text = et.getText().toString(); if (text == null) { return; } app.infoMap.put("Text", text); } }
c. 利用 Room 简化数据库操作
-
Room 框架的导入
-
Room 是 Google 公司推出的基于 SQLite的数据库处理框架,其通过注解技术极大简化了数据库操作,减少了原来相当一部分编码工作量。
-
使用前要在模块的 build.gradle 文件中的
dependencies
节点添加两行配置以导入指定版本的 Room 库implementation 'androidxx.room:room-runtime:2.2.5' annotationProcessor 'androidx.room:room-compiler:2.2.5'
-
-
Room 框架的编码步骤(以录入书籍信息为例,共以下五步)
- 编写书籍信息表对应的实体类:
@Entity
- 编写书籍信息表对应的持久化类:
@Dao
- 编写书籍信息表对应的数据库类,该类从 RoomDatabase 派生而来:
@Database
- 在自定义的 Application 类中声明书籍数据库的唯一实例
- 在操作书籍信息表的地方获取数据表的持久化对象
- 编写书籍信息表对应的实体类:
-
实例:
-
实体类:/enity/BookInfo.java
package com.example.test.enity; import androidx.room.Entity; import androidx.room.PrimaryKey; @Entity public class BookInfo { @PrimaryKey(autoGenerate = true) private int id; private String name; private String author; private String press; private double price; // Generate(生成) - Getter and Setter public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getPress() { return press; } public void setPress(String press) { this.press = press; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "BookInfo{" + "id=" + id + ", name='" + name + '\'' + ", author='" + author + '\'' + ", press='" + press + '\'' + ", price=" + price + '}'; } }
-
持久化类:/dao/BookDao.java(接口 Interface)
package com.example.test.dao; import androidx.room.Dao; import androidx.room.Delete; import androidx.room.Insert; import androidx.room.Query; import androidx.room.Update; import com.example.test.enity.BookInfo; import java.util.List; @Dao public interface BookDao { @Insert void insert(BookInfo... book); // 删除全部 @Query("DELETE FROM BookInfo") void deleteAll(); // 指定删除项 @Delete void delete(BookInfo... book); @Update int update(BookInfo... book);I // 查询所有书籍 @Query("SELECT * FROM BookInfo") List<BookInfo> queryAll(); // 按名称查找书籍 @Query("SELECT * FROM BookInfo WHERE name = :name ORDER BY id DESC limit 1") BookInfo queryByName(String name); }
-
数据库类:/database/BookDatabase.java
package com.example.test.database; import androidx.room.Database; import androidx.room.RoomDatabase; import com.example.test.dao.BookDao; import com.example.test.enity.BookInfo; @Database(entities = {BookInfo.class}, version = 1, exportSchema = true) public abstract class BookDatabase extends RoomDatabase { // 获取该数据库中某张表的持久化对象 public abstract BookDao bookDao(); }
-
entities:表示该数据库所包含的表
-
version:表示该数据库的版本
-
exportSchema:表示是否导出数据库信息的 json 串,设置为 true 时须在 build.gradle 中指定 json 文件的保存路径,内容如下:
android { // ... defaultConfig { // ... javaCompileOptions { annotationProcessorOptions { arguments = ["room.schemaLocation": "$projectDir/schemas".toString()] } } } }
-
-
实例化:/util/MyApplication.java
package com.example.test.util; import android.app.Application; import androidx.room.Room; import com.example.test.database.BookDatabase; public class MyApplication extends Application { private static MyApplication mApp; // 声明一个书籍数据库对象 private BookDatabase bookDatabase; public static MyApplication getInstance() { return mApp; } // 实例化书籍数据库 @Override public void onCreate() { super.onCreate(); mApp = this; // 构建书籍数据库的实例 bookDatabase = Room.databaseBuilder(this, BookDatabase.class, "book") // 允许迁移数据库(发生数据库变更时,Room 会默认删除原数据库再创建新数据库) .addMigrations() // 允许在主线程中操作数据库(Room 默认不能在主线程中操作数据库) .allowMainThreadQueries() .build(); } // 获取书籍数据库的实例 public BookDatabase getBookDatabase() { return bookDatabase; } }
-
在 MainActivity.java 中使用 Room
// ... private BookDao bookDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... // 从 App 实例中获取唯一的书籍持久化对象 bookDao = MyApplication.getInstance().getBookDatabase().bookDao(); } @Override public void onClick(View view) { String name = et_name.getText().toString(); String author = et_author.getText().toString(); String press = et_press.getText().toString(); String price = et_price.getText().toString(); BookInfo b1 = new BookInfo(); b1.setName(name); b1.setAuthor(author); b1.setPress(press); b1.setPrice(Double.parseDouble(price)); switch (view.getId()) { case R.id.btn_ins: bookDao.insert(b1); ToastUtil.show(this, "保存成功"); break; case R.id.btn_del: bi.setId(1); bookDao.delete(bi); ToastUtil.show(this, "删除成功"); break; case R.id.btn_upd: BookInfo bTemp = bookDao.queryByName(name); bi.setId(bTemp.getId()); bi.setName(name); bi.setAuthor(author); bi.setPress(press); bi.setPrice(Double.parseDouble(price)); bookDao.update(bi); break; case R.id.btn_sel: BookInfo bIns = bookDao.queryByName(name); Log.d("SRIGT", bIns.toString()); break; case R.id.btn_sho: StringBuilder str = new StringBuilder(); List<BookInfo> list = bookDao.queryAll(); for (BookInfo b : list) { Log.d("SRIGT", b.toString()); str.append(b).append("\n"); } tv.setText(str.toString()); break; case R.id.btn_cls: bookDao.deleteAll(); break; } }
-
-End-