flutter_isar 保存带有嵌套链接的模型不起作用

问题描述 投票:0回答:1

我正在尝试保存一个具有 IsarLink 的模型,每个模型也都有一个 IsarLink。 保存 IsarLinks(设置为 WorkoutSets)可以工作,但内部的 IsarLink(练习作为练习)不会保留。以下是保存模型以及模型本身的方法。

///contained in a separate class
 static saveWorkout(Workout workout) async {
    await isar!.writeTxn(() async {
      List<Exercise> exercises = workout.workoutExercises.toList();
      await isar!.workouts.put(workout);
      for (Exercise exercise in exercises) {
        await isar!.exercises.put(exercise);
        workout.exercises.add(exercise);
      }

      for (Exercise exercise in exercises) {
        List<WorkoutSet> sets = exercise.sets.toList();
        for (WorkoutSet set in sets) {
          await isar!.workoutSets.put(set); // Save set with link
          set.exercise.value = exercise; // Link set to exercise
          await set.exercise.save();
          workout.sets.add(set); // Prepare to link set to workout
        }
      }

      await workout.sets.save();
      await workout.exercises.save();
      
    });
  }


@Collection(inheritance: false)
class Workout extends Equatable {
  final String id;
  Id get isarId => Crypto.fastHash(id);
  IsarLink<WorkoutTemplate> template = IsarLink<WorkoutTemplate>();

  @override
  @ignore
  List<Object?> get props => [
        id,
        performedOn,
        durationSeconds,
        sets,
        workoutExercises,
        template,
      ];

  @Index()
  DateTime performedOn;
  int durationSeconds = 0;

  Workout({
    required this.id,
    required this.performedOn,
    List<Exercise>? workoutExercises, // Allow passing exercises to constructor
  }) : workoutExercises =
            workoutExercises ?? List<Exercise>.empty(growable: true);

  final sets = IsarLinks<WorkoutSet>();

  ///used only for finding workout by exercises used in the workout e.g. for workout history
  final exercises = IsarLinks<Exercise>();

  @ignore
  final List<Exercise> workoutExercises;

  @ignore
  get totalWeightLifted {
    return sets.fold<double>(
        0, (previousValue, element) => previousValue + (element.weight ?? 0));
  }

  void prepareForSaving() {
    template.value?.exercises = workoutExercises;
  }

  Workout clone() {
    var templateClone = IsarLink<WorkoutTemplate>();
    if (template.value != null) {
      templateClone.value = template.value; // Adjust according to your needs
    }
    List<Exercise> exercisesClone =
        workoutExercises.map((e) => e.clone()).toList();
    return Workout(
      id: id,
      performedOn: DateTime.fromMillisecondsSinceEpoch(
          performedOn.millisecondsSinceEpoch),
      workoutExercises: exercisesClone,
    )
      ..durationSeconds = durationSeconds
      ..template = templateClone;
  }

  addExercises(List<Exercise> exercises) async {
    for (var exercise in exercises) {
      var newExercise = exercise.clone();
      newExercise.sets.add(WorkoutSet(performedAs: 0, exercise: exercise));
      workoutExercises.add(newExercise);
    }
  }

  addSet(int exerciseIndex) async {
    workoutExercises[exerciseIndex].sets.add(WorkoutSet(
        performedAs: workoutExercises[exerciseIndex].sets.length,
        exercise: workoutExercises[exerciseIndex]));
  }

  removeSet(int exerciseIndex, int setIndex) {
    workoutExercises[exerciseIndex].sets.removeAt(setIndex);
    for (final (index, set) in workoutExercises[exerciseIndex].sets.indexed) {
      set.performedAs = index;
    }
  }

  Exercise? getExercise(int index) {
    var id = template.value?.exerciseIds.elementAtOrNull(index);
    if (id == null) {
      return null;
    }
    return Database.isar!.exercises
        .where()
        .idEqualTo(int.parse(id))
        .findFirstSync();
  }

  factory Workout.empty() {
    return Workout(
      id: Uuid().v4(),
      performedOn: DateTime.now(),
    );
  }
}


@Collection(inheritance: false)
class WorkoutSet extends Equatable {
  WorkoutSet({
    this.performedOn,
    this.weight,
    this.reps,
    this.type = SetType.work,
    required this.performedAs,
    this.completed = false,
    this.note,
    this.isChecked = false,
    this.rpe,
    this.restTimer,
    this.autoRestTimer,
    Exercise? exercise,
  }) : uuid = Uuid().v4() {
    this.exercise.value = exercise;
  }

  @override
  @ignore
  List<Object?> get props => [
        performedOn,
        weight,
        reps,
        type,
        performedAs,
        completed,
        note,
        isChecked,
      ];

  WorkoutSet clone() {
    return WorkoutSet(
      performedOn:
          performedOn, // DateTime is immutable in Dart, so direct assignment is okay
      weight: weight,
      reps: reps,
      type: type, // Enums are immutable
      performedAs: performedAs,
      // Add the rest of the properties following the same pattern
      rpe: rpe,
      restTimer: restTimer,
      autoRestTimer: autoRestTimer,
      completed: completed,
      note: note,
      isChecked: isChecked,
      exercise: exercise.value,
    )
      ..id = id
      // ..exercise = exercise
      ..uuid = uuid;
  }

  // LINK PR
  Id id = Isar.autoIncrement;
  String uuid;
  IsarLink<Exercise> exercise = IsarLink<Exercise>();
  @enumerated
  SetType type;
  int? weight;
  int? reps;
  int? rpe; // e.g. 8.5 = 85
  int? restTimer; // in seconds e.g. 300 = 5 Minutes
  int? autoRestTimer;
  bool completed = false;
  String? note;
  bool isChecked = false;
  DateTime? performedOn;
  int performedAs; // represents,  when - during a number of sets of the same exercise - this set was performed
}

enum SetType {
  work,
  warmup,
  dropSet,
  failure,
}

extension Utils on SetType {
  Color color(BuildContext context) {
    switch (this) {
      case SetType.work:
        return Theme.of(context).colorScheme.secondaryContainer;
      case SetType.warmup:
        return Colors.yellow.shade200;
      case SetType.dropSet:
        return Colors.purple.shade200;
      case SetType.failure:
        return Colors.redAccent.shade100;
      default:
        return Theme.of(context).colorScheme.secondaryContainer;
    }
  }

  Color textColor(BuildContext context) {
    switch (this) {
      case SetType.work:
        return Theme.of(context).colorScheme.onSurface;
      case SetType.warmup:
        return Colors.yellow.shade800;
      case SetType.dropSet:
        return Colors.purple.shade800;
      case SetType.failure:
        return Colors.redAccent.shade700;
      default:
        return Theme.of(context).colorScheme.secondaryContainer;
    }
  }
}

extension Formatting on SetType {
  String format() {
    return name.toUpperCase();
  }
}

enum BarType {
  olympic,
  short,
  ez,
  hex,
  none,
}

enum UnitType {
  metric,
  imperial,
}



我尝试在保存后再次进行锻炼,但这不会改变任何东西。

flutter dart flutter-isar
1个回答
0
投票

尝试了很多变体,但都不起作用。最终只是简单地存储所需练习的 ID 并为其实现 getter,而不是使用链接。

© www.soinside.com 2019 - 2024. All rights reserved.