房间在数据库中使用自己的对象(实体中的子实体)

Room working with own objects in a database (sub-entities in entity)

我一直在研究这段时间,以找出解决这个问题的最佳和最简单的方法。 假设我想将一个实体放入另一个实体

@Entity(tableName = "user")
public class User {

   @PrimaryKey(autoGenerate = true)
   private Long id;

   @ColumnInfo(name = "firstName")
   private String firstName;

   @ColumnInfo(name = "lastName")
   private String lastName;


   //getters & setters
}

ORMLite 支持将自己的对象(实体)存储到另一个实体中,并且它还包含在 table 中(不像 @Embedded in Room)。但是我发现房间不支持这样的东西。所以我的解决方案是将该实体的 ID 添加到目标实体。 (下面的代码是从评论上方的用户实体中截取的)

   @ForeignKey(entity = Photo.class, parentColumns = "id", childColumns = "userPhotoId")
   @ColumnInfo(name = "userPhotoId")
   private Long userPhotoId;

   @ForeignKey(entity = Home.class, parentColumns = "id", childColumns = "userHomeId")
   @ColumnInfo(name = "userHomeId")
   private Long userHomeId;

除此之外,我应该添加带有@Ignore 注释的实体,例如

   @Ignore
   private Photo userPhoto;

   @Ignore
   private House userHome;

然后我有用于数据管理的 getter 和 setter。

我现在就是用这种方式设置数据的。在我看来,这是一个非常复杂的解决方案。

public void insertUser(@NonNull User user) {
    new AsyncTask<User, Void, Void>() {

        @Override
        protected Void doInBackground(User... users) {
            User newUser = users[0];

            Photo photo = newUser.getUserPhoto();
            House home = newUser.getUserHome();
            Long photoId = dao.insert(photo);
            Long houseId = dao.insert(home);

            newUser.setUserPhotoId(photoId);
            newUser.setUserHouseId(houseId);

            dao.insert(newUser);
            return null;
        }
    }.execute(user);
}

关于获取数据的逻辑,我使用的是观察者。

LiveData<User> userLiveData = dao.getUserById(userId);
userLiveData.observeForever(new Observer<User>() {
   @Override
   public void onChanged(@Nullable User user) {
   //...
   //the last line will remove an observer before ending.                      
   userLiveData.removeObserver(this);
}

看起来很简单,但是如果你想从数据库中获取更多的数据,那就变得更复杂了。 这不是我要找的。我的想法是

User user = getUserById(..);
user.getPhoto();
//...
//and working without worries

insertUser(myUser);
//and I am sure that the sub-entities were added automatically without any special logic

如果我的查询 return LiveData秒。

或者如果您有任何更好的体验,我将不胜感激。

感谢您的任何想法,我认为这可能对很多人都有帮助。

一周后我找到了解决方案。所以我想分享一下。 所以我的建议是将 Threads(或 AsyncTasks for Android)与 ViewModel 一起使用,不要使用 LiveDatas。

检查下面的代码。

public class MyMV extends AndroidViewModel {
    private MutableLiveData<User> userLiveData = new MutableLiveData();

    //main logic for getting data from a db
    public void getUser(long userId) {
       new Thread(()-> {
          //do not use the '.setValue()', a post method will send a result to observers immediately
          userLiveData.postValue(new User(dao.getUserById(userId));
       }).start();
    }

    //UserLiveData getter
    public LiveData<User> getUserData() {
        return userLiveData;
    }
}

让我们移动到 activity 或 UI

上的某处
//an observer is something like listener
myVM.getUserData().observe(this, user -> {
  //here we can work with user
});

如果您在使用视图模型时遇到问题,可以查看 documentation