Android ROOM - 如何在 RecyclerView 中显示来自 3 个相关实体的数据?

Android ROOM- How can I display data from 3 related entities in a RecyclerView?

基本上,我有 3 个相关实体需要从中获取数据:练习、exercise_workout_junction 和 exercise_workout_goals。

我需要在 RecyclerView 中显示以下内容:

1. exercise_Name (from exercises entity)
2. number_Of_Sets (from workout_goals entity)
3. min_Reps (from workout_goals entity)
4. max_reps (from workout_goals entity) 

(其中 workout_id 是 1、2、3 或 4,具体取决于所选的锻炼,显示的锻炼由 workout_id 决定。)

实现这个的最佳方法是什么?

练习实体


@Entity(tableName = "exercises_table")
public class Exercises {

    @PrimaryKey(autoGenerate = true)
    int exercises_id;

    private String exercise_name;

    @ForeignKey(entity = ExerciseType.class, parentColumns = "exercise_type_id", childColumns = "exercise_type_id")
    private int exercise_type_id;

    @ForeignKey(entity = ExerciseEquipment.class, parentColumns = "exercise_equipment_id", childColumns = "exercise_equipment_id")
    private int exercise_equipment_id;



    public Exercises(String exercise_name, int exercise_type_id, int exercise_equipment_id ) {
        this.exercise_name = exercise_name;
        this.exercise_type_id = exercise_type_id;
        this.exercise_equipment_id = exercise_equipment_id;
    }

    public int getExercise_equipment_id() {
        return exercise_equipment_id;
    }

    public void setExercises_id(int exercise_equipment_id) {
        this.exercises_id = exercises_id;
    }

    public int getExercises_id() {
        return exercises_id;
    }

    public String getExercise_name() {
        return exercise_name;
    }

    public int getExercise_type_id() {
        return exercise_type_id;
    }
}

运动目标实体


@Entity(tableName = "exercise_workout_goals_table")
public class Exercise_Workout_Goals {

    @PrimaryKey(autoGenerate = true)
    private int exercise_workout_goal_id;

    @ForeignKey(entity = Junction.class, parentColumns = "exercise_workout_id", childColumns = "junction_id")
    private int junction_id;

    private int set_number;
    private int min_reps;
    private int max_reps;



    public Exercise_Workout_Goals(int junction_id, int set_number, int min_reps, int max_reps ) {
        this.junction_id = junction_id;
        this.set_number = set_number;
        this.min_reps = min_reps;
        this.max_reps = max_reps;
    }

    public int getExercise_workout_goal_id() {
        return exercise_workout_goal_id;
    }

    public void setExercise_workout_goal_id(int exercise_workout_goal_id) {
        this.exercise_workout_goal_id = exercise_workout_goal_id;
    }

    public int getJunction_id() {
        return junction_id;
    }

    public int getSet_number() {
        return set_number;
    }

    public int getMin_reps() {
        return min_reps;
    }

    public int getMax_reps() {
        return max_reps;
    }
}

连接实体


@Entity(tableName = "exercise_workout_junction_table")
public class Junction {

    @PrimaryKey(autoGenerate = true)
    private int exercise_workout_id;

    @ForeignKey(entity = Exercises.class, parentColumns = "exercises_id", childColumns = "exercise_id")
    int exercise_id;

    @ForeignKey(entity = Workouts.class, parentColumns = "workout_id", childColumns = "workout_id")
    private int workout_id;

    public Junction(int exercise_id, int workout_id) {
        this.exercise_id = exercise_id;
        this.workout_id = workout_id;
    }

    public void setExercise_workout_id(int exercise_workout_id) {
        this.exercise_workout_id = exercise_workout_id;
    }

    public int getExercise_workout_id() {
        return exercise_workout_id;
    }

    public int getExercise_id() {
        return exercise_id;
    }

    public int getWorkout_id() {
        return workout_id;
    }


}

数据库


@Database(entities = {Junction.class, Exercise_Workout_Goals.class, ExerciseEquipment.class,
        Exercises.class, ExerciseType.class, Workouts.class, WorkoutType.class}, version = 4, exportSchema = false)

public abstract class ExerciseDatabase extends RoomDatabase {

    private static ExerciseDatabase instance;

    public abstract JunctionDao junctionDao();
    public abstract ExerciseEquipmentDao exerciseEquipmentDao();
    public abstract WorkoutTypeDao workoutTypeDao();
    public abstract ExercisesDao exercisesDao();
    public abstract WorkoutsDao workoutsDao();
    public abstract ExerciseWorkoutGoalsDao exerciseWorkoutGoalsDao();
    public abstract ExerciseTypeDao exerciseTypeDao();


    //create instance of database
    //synchronised means only one thread at a time can access this method so  you don't accidentally create 2 instances of this database
    public static synchronized ExerciseDatabase getInstance(Context context){
        //we only want to instantiate this database if we don't already have an instance
        if(instance == null){
            //if there is no existing database we want to create one
            instance = Room.databaseBuilder(context.getApplicationContext(),
                    ExerciseDatabase.class, "exercise_database")
                    //this tells room how to migrate to new schema when database version updated to avoid app crashing
                    .fallbackToDestructiveMigration()
                    //this adds the pre-populated database values
                    .addCallback(roomCallback)
                    .build();

        }
        return instance;
    }

    private static RoomDatabase.Callback roomCallback = new RoomDatabase.Callback(){
        @Override
        public void onCreate(@NonNull SupportSQLiteDatabase db) {
            super.onCreate(db);
            new PopulateDbAsyncTask(instance).execute();
        }
    };

    private static class PopulateDbAsyncTask extends AsyncTask<Void,Void,Void> {
        private JunctionDao junctionDao;
        private ExerciseEquipmentDao exerciseEquipmentDao;
        private ExerciseTypeDao exerciseTypeDao;
        private WorkoutTypeDao workoutTypeDao;
        private ExercisesDao exercisesDao;
        private WorkoutsDao workoutsDao;
        private ExerciseWorkoutGoalsDao exerciseWorkoutGoalsDao;





        private PopulateDbAsyncTask(ExerciseDatabase db){
            junctionDao = db.junctionDao();
            exerciseEquipmentDao = db.exerciseEquipmentDao();
            exerciseTypeDao = db.exerciseTypeDao();
            workoutTypeDao = db.workoutTypeDao();
            exercisesDao = db.exercisesDao();
            workoutsDao = db.workoutsDao();
            exerciseWorkoutGoalsDao = db.exerciseWorkoutGoalsDao();
        }

        @Override
        protected Void doInBackground(Void... voids) {

            //  auto inc id
            junctionDao.insert(new Junction(1,1));
            junctionDao.insert(new Junction(2,1));
            junctionDao.insert(new Junction(3,1));
            junctionDao.insert(new Junction(4,1));
            junctionDao.insert(new Junction(5,1));
            junctionDao.insert(new Junction(6,1));
            junctionDao.insert(new Junction(7,1));
            junctionDao.insert(new Junction(8,1));

            junctionDao.insert(new Junction(11,2));
            junctionDao.insert(new Junction(9,2));
            junctionDao.insert(new Junction(1,2));
            junctionDao.insert(new Junction(2,2));
            junctionDao.insert(new Junction(12,2));
            junctionDao.insert(new Junction(13,2));
            junctionDao.insert(new Junction(15,2));
            junctionDao.insert(new Junction(16,2));

            junctionDao.insert(new Junction(9,3));
            junctionDao.insert(new Junction(2,3));
            junctionDao.insert(new Junction(1,3));
            junctionDao.insert(new Junction(5,3));
            junctionDao.insert(new Junction(10,3));
            junctionDao.insert(new Junction(6,3));
            junctionDao.insert(new Junction(7,3));
            junctionDao.insert(new Junction(8,3));

            junctionDao.insert(new Junction(2,4));
            junctionDao.insert(new Junction(1,4));
            junctionDao.insert(new Junction(11,4));
            junctionDao.insert(new Junction(3,4));
            junctionDao.insert(new Junction(12,4));
            junctionDao.insert(new Junction(13,4));
            junctionDao.insert(new Junction(14,4));
            junctionDao.insert(new Junction(15,4));
            junctionDao.insert(new Junction(16,4));


            // Auto inc id
            exerciseEquipmentDao.insert(new ExerciseEquipment("A Person / Something Heavy"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("Pull Up Bar"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("Chair"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("Bands"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("Body-Weight"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("Something heavy you can wedge your legs under/ A training partner\n"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("A form of weight\n"));
            exerciseEquipmentDao.insert(new ExerciseEquipment("Backpack / Other form of weight\n"));

            exerciseTypeDao.insert(new ExerciseType("Shoulders"));  // auto inc ID
            exerciseTypeDao.insert(new ExerciseType("Triceps"));
            exerciseTypeDao.insert(new ExerciseType("Biceps"));
            exerciseTypeDao.insert(new ExerciseType("Chest"));
            exerciseTypeDao.insert(new ExerciseType("Back"));
            exerciseTypeDao.insert(new ExerciseType("Legs"));

            //auto inc id (pk)
            workoutTypeDao.insert(new WorkoutType(" Full-Body"));

            //auto inc primary key
            exercisesDao.insert(new Exercises("Squat",6,1));
            exercisesDao.insert(new Exercises("Pike Push-up",1,6));
            exercisesDao.insert(new Exercises("Weighted Chin-up",5,5));
            exercisesDao.insert(new Exercises("Nordic Hamstring Curls",6,7));
            exercisesDao.insert(new Exercises("Dips",2,8));
            exercisesDao.insert(new Exercises("Lateral Banded Side Raises",1,4));
            exercisesDao.insert(new Exercises("Face Pulls with bands",1,4));
            exercisesDao.insert(new Exercises("Band Bicep Curls",3,4));
            exercisesDao.insert(new Exercises("Weighted Pull-ups",5,5));
            exercisesDao.insert(new Exercises("Bulgarian Split Squats",6,9));
            exercisesDao.insert(new Exercises("Push-ups",4,6));
            exercisesDao.insert(new Exercises("Diamond Push-ups",2,6));
            exercisesDao.insert(new Exercises("Seated Rows with Bands",5,4));
            exercisesDao.insert(new Exercises("Resistance Band Chest Flyes",4,4));
            exercisesDao.insert(new Exercises("Band Tricep Extensions",2,4));
            exercisesDao.insert(new Exercises("Band Shrugs",5,4));



            workoutsDao.insert(new Workouts("A",1));
            workoutsDao.insert(new Workouts("B",1));
            workoutsDao.insert(new Workouts("C",1));
            workoutsDao.insert(new Workouts("D",1));


            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(1,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(2,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(3,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(4,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(5,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(6,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(7,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(8,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(9,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(10,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(11,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(12,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(13,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(14,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(15,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(16,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(17,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(18,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(19,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(20,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(21,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(22,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(23,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(24,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(25,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(26,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(27,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(28,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(29,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(30,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(31,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(32,3,4,50));
            exerciseWorkoutGoalsDao.insert(new Exercise_Workout_Goals(33,3,4,50));

            return null;
        }
    }
}

所以你想执行一个连接操作,然后将数据填充到 recyclerview。 SQL 查询是

SELECT exercises_table.exercise_Name, exercise_workout_goals_table.set_number, exercise_workout_goals_table.min_reps, exercise_workout_goals_table.max_reps FROM exercises_table LEFT JOIN exercise_workout_junction_table ON exercises_table.exercises_id = exercise_workout_junction_table.exercise_workout_id LEFT JOIN exercise_workout_goals_table ON exercise_workout_junction_table.workout_id = exercise_workout_goals_table.exercise_workout_goal_id; 

首先,您创建一个新的 class(比如 ExerciseAndGoal),其中包含连接操作的结果字段。然后在任何 DAO 中,你创建一个 return 类型的 ExerciseAndGoal 列表的新函数。对该 SQL 查询使用注解 @Query("")。

查看教程 https://medium.com/@gokulbalakrishnan/join-queries-room-persistence-library-f0527e7b0da1

现在您可以在后台线程中访问 DAO。假设你使用AsyncTask,你在doInBackground()中这样写。

在 onPostExecute() 中,您会将列表填充到 recycerview。假设您遵循教程并实现了适配器 class。现在您在适配器 class 中有了一个列表。更新列表并调用 notifyDataSetChanged()。

https://developer.android.com/guide/topics/ui/layout/recyclerview