代码之家  ›  专栏  ›  技术社区  ›  Alin

在android房间架构组件中从多到多结构获取LiveData

  •  10
  • Alin  · 技术社区  · 6 年前

    我们举一个基本的例子

    @Entity (tableName="users") 
    class UsersEntity(
         @PrimaryKey val id
         var name:String,
          ...
    ) 
    

    存储角色的表

    @Entity (tableName="roles") 
    class RolesEntity(
         @PrimaryKey val id
         var name:String,
          ...
    ) 
    

    存储用户和角色之间多对多关系的表

    @Entity (tableName="roles") 
    class UserRoles(
         @PrimaryKey val id
         var userId:String,
         var roleId:String
    ) 
    

    我认为我需要的pojo类

    class user(
        var id:String,
        var name:String,
         .... other fields
         var roles: List<Role>
    )
    

    在我的 ViewModel user 结果为 LiveData 也有 List<Role>

    总的来说,我可以:

    • UserDao.getUserById(id) 又回来了 从用户表和 RoleDao.getRolesForUserId(id) 又回来了 实时数据 用户的角色列表。在我的碎片里,我可以 viewModel.getUserById().observe{} viewModel.getRolesForUserId().observe{} . 但这基本上意味着有两个观察员,我很有信心,这不是一条路要走。
    • MediatorLiveData
    2 回复  |  直到 6 年前
        1
  •  3
  •   Dhagz    6 年前

    使用用户及其角色创建一个不同的模型,并使用 @Embedded @Relation

    例如:

    public class UserModel {
      @Embedded
      UserEntity user;
      @Relation(parentColumn = "id", entityColumn = "userId", entity = UserRoles.class)
      List<UserRoleModel> userRoles;
    }
    
    public class UserRoleModel {
      @Embedded
      UserRoles userRole;
      @Relation(parentColumn = "roleId", entityColumn = "id")
      List<RoleEntity> roles; // Only 1 item, but Room wants it to be a list.
    }
    

    你可以使用 UserModel 从这里开始。

        2
  •  1
  •   Sergei Bubenshchikov    6 年前

    在一个屏幕上有多个不同的数据流是可以的。
    一方面我们可以在不更改用户本身的情况下更改用户角色列表;另一方面,可以在不更新角色列表的情况下更改用户名。使用多个数据流的额外好处是,可以在加载用户角色时显示用户数据。
    我想,您有用户和角色的pojo来避免同步问题。您可以实现平滑的数据传递(从数据库到视图),如下面的示例所示:


    视图模型

    public class UserRolesViewModel extends ViewModel {
        private final MutableLiveData<Integer> mSelectedUser;
        private final LiveData<UsersEntity> mUserData;
        private final LiveData<List<RolesEntity>> mRolesData;
        private DataBase mDatabase;
    
        public UserRolesViewModel() {
            mSelectedUser = new MutableLiveData<>();
            // create data flow for user and roles synchronized by mSelectedUser 
            mUserData = Transformations.switchMap(mSelectedUser, mDatabase.getUserDao()::getUser);
            mRolesData = Transformations.switchMap(mSelectedUser, mDatabase.getRolesDao()::getUserRoles);
        }
    
        public void setDatabase(DataBase dataBase) {
            mDatabase = dataBase;
        }
    
        @MainThread
        public void setSelectedUser(Integer userId) {
            if (mDatabase == null)
                throw new IllegalStateException("You need setup database before select user");
            mSelectedUser.setValue(userId);
        }
    
        public LiveData<UsersEntity> getUserData() {
            return mUserData;
        }
    
        public LiveData<List<RolesEntity>> getRolesData() {
            return mRolesData;
        }
    }
    

    Repository 类并通过类注入 this paragraph .

    数据库示例基于 多对多 段落起始于 this article


    实体

    用户

    @Entity(tableName = "users")
    public class UsersEntity {
        @PrimaryKey
        public int id;
        public String name;
    }
    

    @Entity(tableName = "roles")
    public class RolesEntity {
        @PrimaryKey
        public int id;
        public String name;
    }
    

    用户角色

    这个实体需要特别注意,因为我们需要声明 外键 朱恩 徒劳的行动

    @Entity(tableName = "user_roles", primaryKeys = {"user_id", "role_id"}, foreignKeys = {
        @ForeignKey(entity = UsersEntity.class, parentColumns = "id", childColumns = "user_id"),
        @ForeignKey(entity = RolesEntity.class, parentColumns = "id", childColumns = "role_id")
    })
    public class UserRolesEntity {
        @ColumnInfo(name = "user_id")
        public int userId;
        @ColumnInfo(name = "role_id")
        public int roleId;
    }
    

    用户dao

    @Dao
    public interface UserDao {
        @Query("SELECT * from users WHERE id = :userId")
        LiveData<UsersEntity> getUser(int userId);
    }
    

    角色dao

    @Dao
    public interface RolesDao {
        @Query("SELECT * FROM roles INNER JOIN user_roles ON roles.id=user_roles.role_id WHERE user_roles.user_id = :userId")
        LiveData<List<RolesEntity>> getUserRoles(int userId);
    }
    

    数据库

    @Database(entities = {UsersEntity.class, RolesEntity.class, UserRolesEntity.class}, version = 1)
    public abstract class DataBase extends RoomDatabase {
        public abstract UserDao getUserDao();
        public abstract RolesDao getRolesDao();
    }