关于Room:
Room是Android Jetpack组件之一,旨在为Android应用程序提供一种简单、强大且易于使用的本地数据库访问解决方案。
关键特性:
1.基于SQLite封装:Room是基于SQLite数据库引擎构建的,提供了面向对象的API来与SQLite交互,使得开发者无需直接编写SQL语句,降低了SQL错误风险,提高了代码可读性和可维护性。
2.编译时验证:Room利用注解处理器在编译时检查查询语句的有效性,提前发现潜在的SQL语法错误或类型不匹配等问题,增强了开发过程中的错误检查能力。
3.类型安全:Room通过提供数据访问对象(DAO)接口和数据模型类,确保了数据库操作与Java/Kotlin对象之间的类型安全转换,避免了运行时的类型转换异常。
4.LiveData / Flow 支持:Room可以轻松配合LiveData或Kotlin Flow实现数据变化的实时观察与响应,便于在UI层自动更新数据,适用于MVVM架构中的数据绑定。
5.事务管理:Room提供了便捷的事务管理机制,可以通过@Transaction注解在DAO方法上标记,确保一组数据库操作的原子性。
6.查询重用与优化:Room支持定义可重用的查询方法,同时也支持查询缓存以提高性能。
使用要点:
1.定义数据模型类:使用注解(如@Entity、@PrimaryKey、@ColumnInfo等)定义数据库表对应的Java或Kotlin类。
2.创建DAO接口:使用@Dao注解创建数据访问对象接口,定义查询、插入、更新、删除等数据库操作方法。
3.创建RoomDatabase子类:定义一个继承自RoomDatabase的抽象类,声明包含的实体类与DAO。
4.初始化数据库:在应用启动时创建并持有RoomDatabase实例,通常使用单例模式。
5.执行数据库操作:通过获取的DAO实例,调用其方法进行数据库操作。
好了,至此,前面的文案部分摘抄完毕,相信大家也从不少地方看到过很多理论知识,但是实践起来总不是那么的理想化,有各种各样的问题,对吧。
先来看本文实现的效果:
可以看到,demo实现的是非常基础的增删改查功能
下面开始具体的实现
本文使用的开发环境:
Android Studio Iguana | 2023.2.1 Patch 1
gradle-8.4-bin.zip
- //room
- implementation 'androidx.room:room-runtime:2.6.1'
- annotationProcessor 'androidx.room:room-compiler:2.6.1'
- /**
- * 用户类,用于表示用户信息
- */
- @Entity
- public class User {
- // 主键,自动生成
- @PrimaryKey(autoGenerate = true)
- private long id;
- private String name; // 用户名
- private String age; // 年龄
- private String sex; // 性别
-
- /**
- * 构造函数,用于创建一个新的用户实例
- * @param name 用户名
- * @param age 年龄
- * @param sex 性别
- */
- public User(String name, String age, String sex) {
- this.name = name;
- this.age = age;
- this.sex = sex;
- }
-
- /**
- * 获取用户ID
- * @return 用户ID
- */
- public long getId() {
- return id;
- }
-
- /**
- * 设置用户ID
- * @param id 用户ID
- */
- public void setId(long id) {
- this.id = id;
- }
-
- /**
- * 获取用户名
- * @return 用户名
- */
- public String getName() {
- return name;
- }
-
- /**
- * 设置用户名
- * @param name 用户名
- */
- public void setName(String name) {
- this.name = name;
- }
-
- /**
- * 获取用户年龄
- * @return 用户年龄
- */
- public String getAge() {
- return age;
- }
-
- /**
- * 设置用户年龄
- * @param age 用户年龄
- */
- public void setAge(String age) {
- this.age = age;
- }
-
- /**
- * 获取用户性别
- * @return 用户性别
- */
- public String getSex() {
- return sex;
- }
-
- /**
- * 设置用户性别
- * @param sex 用户性别
- */
- public void setSex(String sex) {
- this.sex = sex;
- }
- }
- /**
- * 用户数据访问接口,提供用户数据的增删改查操作。
- */
- @Dao
- public interface UserDao {
-
- /**
- * 插入用户信息到数据库。
- *
- * @param user 需要插入的用户对象。
- */
- @Insert
- void insertUser(User user);
-
- /**
- * 根据用户名查找用户。
- *
- * @param name 要查找的用户名,支持部分匹配。
- * @return 找到的第一个用户对象,如果没有找到返回null。
- */
- @Query("SELECT * FROM user WHERE name LIKE :name LIMIT 1")
- User findUserByName(String name);
-
- /**
- * 更新用户信息。
- *
- * @param user 需要更新的用户对象。
- */
- @Update
- void updateUser(User user);
-
- /**
- * 根据用户名删除用户。
- *
- * @param name 需要删除的用户的用户名。
- */
- @Query("DELETE FROM user WHERE name LIKE :name")
- void deleteUserByName(String name);
-
- /**
- * 查找所有用户信息。
- *
- * @return 用户列表,包含所有用户。
- */
- @Query("SELECT * FROM user")
- List<User> findAllUsers();
-
- /**
- * 删除所有用户信息。
- */
- @Query("DELETE FROM User")
- void deleteAllUsers();
-
- }
- /**
- * 应用的数据库类,继承自RoomDatabase。用于定义数据库的结构和操作。
- * 使用单例模式确保全局仅有一个数据库实例。
- */
- @Database(entities = {User.class}, version = 1, exportSchema = false)
- public abstract class AppDatabase extends RoomDatabase {
- // 静态变量INSTANCE用于存储数据库的单例实例
- private static volatile AppDatabase INSTANCE;
-
- /**
- * 获取AppDatabase的单例实例。
- * 如果实例不存在,则通过Room的databaseBuilder创建一个新的实例。
- * 使用双重检查锁定确保线程安全。
- *
- * @param context 上下文对象,用于访问应用的资源和其他组件。
- * @return AppDatabase的单例实例。
- */
- public static AppDatabase getDatabase(Context context) {
- if (INSTANCE == null) {
- synchronized (AppDatabase.class) {
- if (INSTANCE == null) {
- // 通过Room的databaseBuilder构建数据库实例,配置数据库名称和实体类
- INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
- AppDatabase.class, DATABASE_NAME)
- .fallbackToDestructiveMigration() // 数据库升级时采用破坏性迁移策略
- .build();
- }
- }
- }
- return INSTANCE;
- }
-
- /**
- * 获取UserDao的抽象方法。UserDao是一个接口,用于操作用户数据。
- * 需要在具体实现类中提供该方法的具体实现。
- *
- * @return UserDao接口实例,用于进行用户数据的增删改查操作。
- */
- public abstract UserDao getUserDao();
- }
- public class Constant {
- // 数据库名称常量
- public static final String DATABASE_NAME = "app_database";
- public static final String RESULT_MESSAGE_USER_NOT_EXIST = "用户不存在";
- public static final String RESULT_MESSAGE_USER_EXIST = "用户已存在";
- public static final String RESULT_MESSAGE_ERROR = "操作失败";
- }
至此,User表已经建立完成,接下来开始数据库操作方法
需要说明的是
本文实现的demo基于Android MVVM设计模式,所以并不会在Activity中直接操作数据库,一般来说,与用户相关的数据操作的部分需要放在ViewModel层,同时建议定义一个Repository来处理数据库操作,这样的话,最终的调用模式就是:
1.Repository层处理数据库的增删改查操作
2.ViewModel层处理与用户相关的数据操作逻辑
3.Activity用来更新UI
这样做一方面满足了MVVM的设计模式,同时也减轻了ViewModel层的负担
那么继续分享代码:
- /**
- * 用户仓库类,负责用户数据的增删改查操作。
- */
- public class UserRepository {
- private final UserDao userDao;
-
- /**
- * 构造函数,初始化用户数据访问对象。
- *
- * @param database 应用数据库实例。
- */
- public UserRepository(AppDatabase database) {
- this.userDao = database.getUserDao();
- }
-
- /**
- * 插入用户。如果用户已存在,则操作失败。
- *
- * @param user 要插入的用户对象。
- * @return 返回操作结果,成功或失败。
- */
- @Transaction
- public UserRepositoryResult insertUser(User user) {
- // 检查用户是否已存在
- if (userDao.findUserByName(user.getName()) != null) {
- return new UserRepositoryResult(
- UserRepositoryResult.Type.FAILURE,
- RESULT_MESSAGE_USER_EXIST);
- }
- userDao.insertUser(user);
- return UserRepositoryResult.success();
- }
-
- /**
- * 更新用户信息。如果用户不存在,则操作失败。
- *
- * @param user 要更新的用户对象。
- * @return 返回操作结果,成功或失败。
- */
- @Transaction
- public UserRepositoryResult updateUser(User user) {
- // 确认用户存在
- User findUser = userDao.findUserByName(user.getName());
- if (findUser == null) {
- return new UserRepositoryResult(
- UserRepositoryResult.Type.FAILURE,
- RESULT_MESSAGE_USER_NOT_EXIST);
- }
- user.setId(findUser.getId());
- userDao.updateUser(user);
- return UserRepositoryResult.success();
- }
-
- /**
- * 根据用户名删除用户。如果用户不存在,则操作失败。
- *
- * @param name 要删除的用户的用户名。
- * @return 返回操作结果,成功或失败。
- */
- @Transaction
- public UserRepositoryResult deleteUserByName(String name) {
- // 确认用户存在
- if (userDao.findUserByName(name) == null) {
- return new UserRepositoryResult(
- UserRepositoryResult.Type.FAILURE,
- RESULT_MESSAGE_USER_NOT_EXIST);
- }
- userDao.deleteUserByName(name);
- return UserRepositoryResult.success();
- }
-
- /**
- * 删除所有用户。
- *
- * @return 返回操作结果,成功。
- */
- @Transaction
- public UserRepositoryResult deleteAllUsers() {
- userDao.deleteAllUsers();
- return UserRepositoryResult.success();
- }
-
- /**
- * 根据用户名查找用户。如果用户不存在,则操作失败。
- *
- * @param name 要查找的用户的用户名。
- * @return 返回操作结果,包含查找到的用户列表,如果未找到则列表为空。
- */
- @Transaction
- public UserRepositoryResult findUserByName(String name) {
- User user = userDao.findUserByName(name);
- // 处理用户不存在的情况
- if (user == null) {
- return new UserRepositoryResult(
- UserRepositoryResult.Type.FAILURE,
- RESULT_MESSAGE_USER_NOT_EXIST);
- }
- List<User> list = new ArrayList<>();
- list.add(user);
- return UserRepositoryResult.success(list);
- }
-
- /**
- * 查找所有用户。
- *
- * @return 返回操作结果,包含所有用户列表。
- */
- @Transaction
- public UserRepositoryResult findAllUsers() {
- List<User> list = userDao.findAllUsers();
- return UserRepositoryResult.success(list);
- }
- }
- /**
- * 用户仓库操作结果类,用于封装用户操作的结果信息。
- */
- public class UserRepositoryResult {
- /**
- * 操作结果类型,包括成功和失败。
- */
- public enum Type {
- SUCCESS,
- FAILURE
- }
-
- private final Type type; // 操作结果类型
- private final String errorMessage; // 错误信息,当操作失败时使用
-
- // 成功操作时找到的用户列表
- private final List<User> foundUserList = new ArrayList<>();
-
- /**
- * 构造函数,用于创建一个操作结果实例。
- *
- * @param type 操作结果类型(成功或失败)。
- * @param errorMessage 错误信息,如果操作成功,则可以为null。
- */
- public UserRepositoryResult(Type type, String errorMessage) {
- this.type = type;
- this.errorMessage = errorMessage;
- }
-
- /**
- * 构造函数,用于创建一个包含用户列表的操作结果实例。
- *
- * @param type 操作结果类型(成功或失败)。
- * @param errorMessage 错误信息,如果操作成功,则可以为null。
- * @param foundUserList 找到的用户列表,如果操作没有找到用户,可以为null或空列表。
- */
- public UserRepositoryResult(Type type, String errorMessage, List<User> foundUserList) {
- this.type = type;
- this.errorMessage = errorMessage;
- if(null != foundUserList && !foundUserList.isEmpty()){
- this.foundUserList.addAll(foundUserList);
- }
- }
-
- /**
- * 获取操作结果类型。
- *
- * @return 返回操作结果类型(成功或失败)。
- */
- public Type getType() {
- return type;
- }
-
- /**
- * 获取错误信息。
- *
- * @return 如果操作成功,返回null;否则返回错误信息字符串。
- */
- public String getErrorMessage() {
- return errorMessage;
- }
-
- /**
- * 获取找到的用户列表。
- *
- * @return 返回操作成功时找到的用户列表,可能为空。
- */
- public List<User> getFoundUserList() {
- return foundUserList;
- }
-
- /**
- * 创建一个表示操作成功的UserRepositoryResult实例。
- *
- * @param foundUserList 找到的用户列表,可以为null。
- * @return 返回一个初始化为成功类型且包含指定用户列表的UserRepositoryResult实例。
- */
- public static UserRepositoryResult success(List<User> foundUserList) {
- return new UserRepositoryResult(Type.SUCCESS, null, foundUserList);
- }
-
- /**
- * 创建一个表示操作成功的UserRepositoryResult实例(不包含用户列表)。
- *
- * @return 返回一个初始化为成功类型且不包含用户列表的UserRepositoryResult实例。
- */
- public static UserRepositoryResult success() {
- return new UserRepositoryResult(Type.SUCCESS, null, null);
- }
-
- /**
- * 创建一个表示操作失败的UserRepositoryResult实例。
- *
- * @param errorMessage 错误信息字符串。
- * @return 返回一个初始化为失败类型且包含指定错误信息的UserRepositoryResult实例。
- */
- public static UserRepositoryResult failure(String errorMessage) {
- return new UserRepositoryResult(Type.FAILURE, errorMessage, null);
- }
-
- }
- /**
- * 主要的ViewModel类,用于处理与用户相关的数据操作。
- */
- public class MainViewModel extends ViewModel {
- // 用户数据仓库接口
- private final UserRepository userRepository;
- // 执行器服务,用于在后台线程中执行数据库操作
- private static final ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor();
-
- /**
- * 构造函数,初始化用户数据仓库。
- *
- * @param userRepository 用户数据仓库实例。
- */
- public MainViewModel(UserRepository userRepository) {
- this.userRepository = userRepository;
- }
-
- // 用于存储插入用户操作结果的LiveData对象
- private final MutableLiveData<UserRepositoryResult> insertUserResult = new MutableLiveData<>();
-
- /**
- * 获取插入用户操作的结果。
- *
- * @return UserRepositoryResult 插入操作的结果。
- */
- public LiveData<UserRepositoryResult> getInsertUserResult() {
- return insertUserResult;
- }
-
- // 用于存储更新用户操作结果的LiveData对象
- private final MutableLiveData<UserRepositoryResult> updateUserResult = new MutableLiveData<>();
-
- /**
- * 获取更新用户操作的结果。
- *
- * @return UserRepositoryResult 更新操作的结果。
- */
- public LiveData<UserRepositoryResult> getUpdateUserResult() {
- return updateUserResult;
- }
-
- // 用于存储根据名称删除用户操作结果的LiveData对象
- private final MutableLiveData<UserRepositoryResult> deleteUserByNameResult = new MutableLiveData<>();
-
- /**
- * 获取根据名称删除用户操作的结果。
- *
- * @return UserRepositoryResult 删除操作的结果。
- */
- public LiveData<UserRepositoryResult> getDeleteUserByNameResult() {
- return deleteUserByNameResult;
- }
-
- // 用于存储删除所有用户操作结果的LiveData对象
- private final MutableLiveData<UserRepositoryResult> deleteAllUsersResult = new MutableLiveData<>();
-
- /**
- * 获取删除所有用户操作的结果。
- *
- * @return UserRepositoryResult 删除操作的结果。
- */
- public LiveData<UserRepositoryResult> getDeleteAllUsersResult() {
- return deleteAllUsersResult;
- }
-
- // 用于存储根据名称查找用户操作结果的LiveData对象
- private final MutableLiveData<UserRepositoryResult> findUserByNameResult = new MutableLiveData<>();
-
- /**
- * 获取根据名称查找用户操作的结果。
- *
- * @return UserRepositoryResult 查找操作的结果。
- */
- public LiveData<UserRepositoryResult> getFindUserByNameResult() {
- return findUserByNameResult;
- }
-
- // 用于存储查找所有用户操作结果的LiveData对象
- private final MutableLiveData<UserRepositoryResult> findAllUsersResult = new MutableLiveData<>();
-
- /**
- * 获取查找所有用户操作的结果。
- *
- * @return UserRepositoryResult 查找操作的结果。
- */
- public LiveData<UserRepositoryResult> getFindAllUsersResult() {
- return findAllUsersResult;
- }
-
- /**
- * 在后台线程中执行用户数据操作。
- */
- // 插入用户
- public void insertUser(final User user) {
- EXECUTOR_SERVICE.execute(() -> {
- insertUserResult.postValue(userRepository.insertUser(user));
- });
- }
-
- // 更新用户
- public void updateUser(final User user) {
- EXECUTOR_SERVICE.execute(() -> {
- updateUserResult.postValue(userRepository.updateUser(user));
- });
- }
-
- // 根据名称删除用户
- public void deleteUserByName(final String name) {
- EXECUTOR_SERVICE.execute(() -> {
- deleteUserByNameResult.postValue(userRepository.deleteUserByName(name));
- });
- }
-
- // 删除所有用户
- public void deleteAllUsers() {
- EXECUTOR_SERVICE.execute(() -> {
- deleteAllUsersResult.postValue(userRepository.deleteAllUsers());
- });
- }
-
- // 根据名称查找用户
- public void findUserByName(final String name) {
- EXECUTOR_SERVICE.execute(() -> {
- findUserByNameResult.postValue(userRepository.findUserByName(name));
- });
- }
-
- // 查找所有用户
- public void findAllUsers() {
- EXECUTOR_SERVICE.execute(() -> {
- findAllUsersResult.postValue(userRepository.findAllUsers());
- });
- }
-
- /**
- * ViewModel工厂类,用于创建MainViewModel实例。
- */
- public static class Factory extends ViewModelProvider.NewInstanceFactory {
- // 用户数据仓库实例
- private final UserRepository userRepository;
-
- /**
- * 构造函数,初始化用户数据仓库。
- *
- * @param userRepository 用户数据仓库实例。
- */
- public Factory(UserRepository userRepository) {
- this.userRepository = userRepository;
- }
-
- /**
- * 创建MainViewModel实例。
- *
- * @param modelClass ViewModel的类类型。
- * @return MainViewModel 实例。
- */
- @NonNull
- @Override
- public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
- return (T) new MainViewModel(userRepository);
- }
- }
-
- }
- /**
- * 主活动类,负责管理应用程序的主要界面。
- */
- public class MainActivity extends AppCompatActivity {
-
- private MainViewModel viewModel; // 视图模型,用于管理活动背后的业务逻辑
- private ActivityMainBinding binding; // 数据绑定实例,用于简化UI更新
- private UserRepository userRepository;
-
- /**
- * 在活动创建时调用。
- *shaoshao
- * @param savedInstanceState 如果活动之前被销毁,这参数包含之前的状态。如果活动没被销毁之前,这参数是null。
- */
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // 启用边缘到边缘的UI
- EdgeToEdge.enable(this);
- // 设置数据绑定
- binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
- // 设置视图的内边距,以适应系统栏位的高度
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
- Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
- return insets;
- });
- userRepository = new UserRepository(AppDatabase.getDatabase(MVVMApplication.getInstance()));
- // 初始化视图模型
- viewModel = new ViewModelProvider(this, new MainViewModel.Factory(userRepository)).get(MainViewModel.class);
- binding.setViewModel(viewModel);
- initListeners();
- initObserver();
- }
-
- /**
- * 初始化视图监听器。
- */
- private void initListeners() {
- // 清空输入框操作监听
- binding.btnClearEdit.setOnClickListener(v -> {
- clearEditText();
- });
-
- // 插入用户操作监听
- binding.btnInsert.setOnClickListener(v -> {
- User userChecked = checkUserInfo();
- if (userChecked != null) {
- viewModel.insertUser(userChecked);
- }
- });
-
- // 根据姓名查找用户操作监听
- binding.btnFindByName.setOnClickListener(v -> {
- String nameChecked = checkName();
- if (!nameChecked.isEmpty()) {
- viewModel.findUserByName(nameChecked);
- }
- });
-
- // 更新用户操作监听
- binding.btnUpdate.setOnClickListener(v -> {
- User userChecked = checkUserInfo();
- if (userChecked != null) {
- viewModel.updateUser(userChecked);
- }
- });
-
- // 根据姓名删除用户操作监听
- binding.btnDeleteByName.setOnClickListener(v -> {
- String nameChecked = checkName();
- if (!nameChecked.isEmpty()) {
- viewModel.deleteUserByName(nameChecked);
- }
- });
-
- // 查找所有用户操作监听
- binding.btnFindAll.setOnClickListener(v -> {
- viewModel.findAllUsers();
- });
-
- // 删除所有用户操作监听
- binding.btnDeleteAll.setOnClickListener(v -> {
- viewModel.deleteAllUsers();
- });
-
- }
-
- private void initObserver() {
- // 观察插入结果
- viewModel.getInsertUserResult().observe(this, result -> {
- if (result.getType() == UserRepositoryResult.Type.SUCCESS) {
- showToast("添加成功");
- } else {
- showToast(result.getErrorMessage());
- }
- });
-
- // 观察查找结果
- viewModel.getFindUserByNameResult().observe(this, result -> {
- if (result.getType() == UserRepositoryResult.Type.SUCCESS) {
- if (!result.getFoundUserList().isEmpty()) {
- User user = result.getFoundUserList().get(0);
- binding.etName.setText(user.getName());
- binding.etAge.setText(user.getAge());
- binding.etSex.setText(user.getSex());
- } else {
- showToast("未找到该用户");
- }
- } else {
- showToast(result.getErrorMessage());
- }
- });
-
- // 观察更新结果
- viewModel.getUpdateUserResult().observe(this, result -> {
- if (result.getType() == UserRepositoryResult.Type.SUCCESS) {
- showToast("更新成功");
- } else {
- showToast(result.getErrorMessage());
- }
- });
-
- // 观察删除结果
- viewModel.getDeleteUserByNameResult().observe(this, result -> {
- if (result.getType() == UserRepositoryResult.Type.SUCCESS) {
- showToast("删除成功");
- } else {
- showToast(result.getErrorMessage());
- }
- });
-
- // 观察查找所有用户的结果
- viewModel.getFindAllUsersResult().observe(this, result -> {
- if (result.getType() == UserRepositoryResult.Type.SUCCESS) {
- List<User> userList = result.getFoundUserList();
- if (!userList.isEmpty()) {
- StringBuilder sb = new StringBuilder();
- for (User user : userList) {
- sb.append(user.getName()).append(" ").append(user.getAge()).append(" ").append(user.getSex()).append("\n");
- }
- showToast(sb.toString());
- } else {
- showToast("没有用户");
- }
- } else {
- showToast(result.getErrorMessage());
- }
- });
-
- // 观察删除所有用户的结果
- viewModel.getDeleteAllUsersResult().observe(this, result -> {
- if (result.getType() == UserRepositoryResult.Type.SUCCESS) {
- showToast("删除成功");
- } else {
- showToast(result.getErrorMessage());
- }
- });
- }
-
- // 封装对用户信息输入的验证
- private User checkUserInfo() {
- String name = binding.etName.getText().toString();
- if (name.isEmpty()) {
- showToast("请输入姓名");
- return null;
- }
- String age = binding.etAge.getText().toString();
- if (age.isEmpty()) {
- showToast("请输入年龄");
- return null;
- }
- String sex = binding.etSex.getText().toString();
- if (sex.isEmpty()) {
- showToast("请输入性别");
- return null;
- }
- return new User(name, age, sex);
- }
-
- // 封装对姓名输入的检查
- private String checkName() {
- String name = binding.etName.getText().toString();
- if (name.isEmpty()) {
- showToast("请输入姓名");
- return "";
- }
- return name;
- }
-
- // 清除编辑文本框中的内容
- private void clearEditText() {
- binding.etName.setText("");
- binding.etAge.setText("");
- binding.etSex.setText("");
- }
-
- // 简化Toast消息的显示
- private void showToast(String message) {
- Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
- }
-
- }
- <?xml version="1.0" encoding="utf-8"?>
- <!--使用databinding功能,根布局需要使用<layout>标签 -->
- <layout 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">
-
- <!-- 这是Data Binding的<data>标签,用于定义布局中使用的数据对象和表达式-->
- <data>
- <variable
- name="viewModel"
- type="com.example.mvvmdemo.ui.main.MainViewModel" />
- </data>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/main"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".ui.main.MainActivity">
-
- <EditText
- android:id="@+id/et_name"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginEnd="10dp"
- android:ems="10"
- android:hint="姓名"
- android:inputType="text"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintVertical_bias="0.05" />
-
- <EditText
- android:id="@+id/et_age"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:ems="10"
- android:hint="年龄"
- android:inputType="text"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/et_name" />
-
- <EditText
- android:id="@+id/et_sex"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:ems="10"
- android:hint="性别"
- android:inputType="text"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/et_age" />
-
- <Button
- android:id="@+id/btn_insert"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:text="增加"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="1.0"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/btn_clear_edit" />
-
- <Button
- android:id="@+id/btn_find_by_name"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:text="根据姓名查询"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/btn_insert" />
-
- <Button
- android:id="@+id/btn_update"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:text="更新"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="0.0"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/btn_find_by_name" />
-
- <Button
- android:id="@+id/btn_find_all"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:text="查询所有"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="0.0"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/btn_delete_by_name" />
-
- <Button
- android:id="@+id/btn_delete_by_name"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:text="根据姓名删除"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/btn_update" />
-
- <Button
- android:id="@+id/btn_delete_all"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginStart="10dp"
- android:layout_marginTop="10dp"
- android:layout_marginEnd="10dp"
- android:layout_marginBottom="80dp"
- android:text="清空数据表"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="1.0"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/btn_find_all"
- app:layout_constraintVertical_bias="0.0" />
-
- <Button
- android:id="@+id/btn_clear_edit"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dp"
- android:text="清空输入"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/et_sex" />
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- </layout>
其实关于MVVM的代码并不好写,因为MVVM是一种编程思想,并没有确定的写法和流派,所以建议每一个学习MVVM的同学,不要只是盲目的死扣形式,而是要追求代码的内在。不管是何种形式,只要是使得代码条理更清晰,功能稳定,就是好代码。代码这种东西,没有尽头,今天我们学习MVVM设计模式,可能不知道什么时候,又兴起来一种新的形式,就像潮起潮落一样。
然后关于我上面展示的代码,我没有做过多的解释,主要是快下班了,我今天太想要把这篇积压已久的文章整理好发出去,哈哈。不过也附带了足够多的代码注释,如果你真的很希望掌握Room的用法,也建议你能够对照着代码多看,然后在自己的开发环境里多运行几次,然后把demo进行一些功能扩展和修改,相信你一定可以掌握的很好。