具有新线程和数据绑定问题的房间持久库

Posted

技术标签:

【中文标题】具有新线程和数据绑定问题的房间持久库【英文标题】:Room persistent library with new Thread and data-binding issue 【发布时间】:2017-10-29 17:24:59 【问题描述】:

我正在开发 android Room Persistent 库。我还在我的项目中实现了双向数据绑定。在项目中,我通过填写表单并按行显示所有用户并通过单击特定用户行来更新它们来插入用户。下面是我的 UserDao 类:

@Dao
public interface UserDao 

  @Query("SELECT * FROM user")
  List<User> getAllUsers();

  @Insert
  void insertAll(User... users);

  @Update
  void updateUser(User... users);

  @Query("SELECT * FROM user WHERE user_id IN (:userId)")
  User getSpecifiedUser(int...userId);
 

对于数据绑定,我在 UserFormActivity 中绑定用户模型

binding.setUserModel(userModel);

现在,由于 Room 持久库不允许您在主线程中执行任何数据库操作,为了更新用户,我通过单击新线程中的行来获取用户表单中特定用户的数据,如下所示:

 private void getUserFormData(final int userId) 
    try 
        Thread t = new Thread(new Runnable() 
            public void run() 
                userModel = db.userDao().getSpecifiedUser(userId);
            
        , "Thread A");
        t.start();
     catch (NumberFormatException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

在 userModel 中获取用户数据进行更新后,我希望用户数据反映在执行数据绑定的用户表单中,但它没有反映。我被这个问题困住了。

【问题讨论】:

您在 Room 文档的哪个部分阅读了“Room 持久库不允许您在主线程中执行任何数据库操作”? 我不明白一件事,如果你在加载对象之前设置了绑定,怎么能更新呢?你不应该在从 db 加载它之后调用 binding.setUserModel(userModel) 吗? @MatPag:没有记录,但是如果您尝试在主应用程序线程上执行 Room I/O,Room 会抛出异常。 使用LiveData,或AsyncTask,或事件总线,或RxJava/RxAndroid,或在后台线程上做查询,然后安排在主应用程序线程上更新你的UI .特别是 Room 是为与 LiveDataViewModel 和其他架构组件一起使用而设计的。 这里记录和解释:developer.android.com/reference/android/arch/persistence/room/…. 【参考方案1】:

我在我的项目中实现了 LiveData 和 ViewModel,还在我的 UserListActivity 中扩展了 LifecycleActivity。这是我的 AddUserViewModel 类:

public class AddUserViewModel extends AndroidViewModel 
     private UserDatabase userDatabase;

     public AddUserViewModel(Application application) 
      super(application);

     userDatabase = UserDatabase.getDatabase(this.getApplication());
     

     public void addUser(User user) 
     new AddUserAsyncTask(userDatabase).execute(user);
     

     private static class AddUserAsyncTask extends AsyncTask<User, Void, 
        Void> 

        private UserDatabase db;

        public AddUserAsyncTask(UserDatabase userDatabase) 
             db = userDatabase;
        

     @Override
     protected Void doInBackground(User... params) 
         db.userDao().insertUser(params);
         return null;
         
     

    public User getSpecificUserData(int userId) 
        User user = null;
        try 
             user = new 
             getUserDataAsyncTask(userDatabase).execute(userId).get();
         catch (InterruptedException | ExecutionException e) 
            e.printStackTrace();
           
        return user;
    

    private static class getUserDataAsyncTask extends AsyncTask<Integer, 
        Void, User> 

        private UserDatabase db;

        public getUserDataAsyncTask(UserDatabase userDatabase) 
            db = userDatabase;
        

        @Override
        protected User doInBackground(Integer... userId) 
            User user = db.userDao().getSpecifiedUser(userId);
            return user;
        

        @Override
        protected void onPostExecute(User user) 
            super.onPostExecute(user);
        
      
  

在 AddUserActivity 中,我从数据库方法中获取特定的用户数据

userModel = addUserViewModel.getSpecificUserData(userId);

并在单击提交按钮时更新数据。我的 UserListActivity 扩展了 LifecycleActivity ,其中用户列表被观察到,当有变化时,它会更新 Use 列表,如下所示:

 userViewModel = ViewModelProviders.of(this).get(UserViewModel.class);

    userViewModel.getUserList().observe(UserListActivity.this, new 
    Observer<List<User>>() 
        @Override
        public void onChanged(@Nullable List<User> user) 
            adapter.addItems(user);
        
    );

这对我来说很好,我得到了解决方案!

【讨论】:

以上是关于具有新线程和数据绑定问题的房间持久库的主要内容,如果未能解决你的问题,请参考以下文章

如何在房间持久性库中插入图像?

Android 房间持久性库:Upsert

Android房间分页不起作用

房间持久化库和内容提供者

房间持久性库。删除所有

将 MVVM 架构中的 Tab 布局与数据绑定库一起使用