Флаттер: Как сохранить данные при возврате на экран, после ухода? - PullRequest
0 голосов
/ 11 апреля 2020

Проблема: я могу создавать упражнения и добавлять их в анимированный список в CustomExScreen.

Когда я возвращаюсь на предыдущий уровень стека, будучи MenuScreen (), а затем повторно посещаю мой список упражнений, мои ранее отправленные данные удаляются. , Как сохранить состояние данных даже при выходе из виджета? Сохраните стек и восстановите его. Заранее спасибо!

CustomExScreenState

class CustomExScreen extends StatefulWidget {
  @override
  CustomExScreenState createState() => CustomExScreenState();
}

class CustomExScreenState extends State<CustomExScreen>
    with TickerProviderStateMixin {
  List<Exerciselist> items = new List<Exerciselist>();
  GlobalKey<AnimatedListState> animatedListKey = GlobalKey<AnimatedListState>();
  AnimationController emptyListController;

  @override
  void initState() {
    emptyListController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 200),
    );
    emptyListController.forward();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'CUSTOM EXERCISES',
          key: Key('main-app-title'),
        ),
        centerTitle: true,
      ),
      floatingActionButton: Container(
        child: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () => goToNewItemView(),
        ),
      ),
      body: renderBody(),
    );
  }

  Widget renderBody() {
    if (items.length > 0) {
      return buildListView();
    } else {
      return emptyList();
    }
  }

  Widget emptyList() {
    return Center(
        child: FadeTransition(
            opacity: emptyListController,
            child: Text('No exercise, press + to add some!')));
  }

  Widget buildListView() {
    return AnimatedList(
      key: animatedListKey,
      initialItemCount: items.length,
      itemBuilder: (BuildContext context, int index, animation) {
        setState(() {
          buildItem(items[index], index);
        });
        return SizeTransition(
          sizeFactor: animation,
          child: buildItem(items[index], index),
        );
      },
    );
  }

  Widget buildItem(Exerciselist item, int index) {
    return Dismissible(
      key: Key('${item.hashCode}'),
      background: Container(color: Colors.red[700]),
      onDismissed: (direction) => removeItemFromList(item, index),
      direction: DismissDirection.startToEnd,
      child: buildListTile(item, index),
    );
  }

  Widget buildListTile(item, index) {
    return ListTile(
      onTap: () => changeItemCompleteness(item),
      onLongPress: () => goToEditItemView(item),
      title: Text(
        item.title,
        key: Key('item-$index'),
        style: TextStyle(
            color: item.completed ? Colors.grey : Colors.black,
            decoration: item.completed ? TextDecoration.lineThrough : null),
      ),
      trailing: Icon(
        item.completed ? Icons.check_box : Icons.check_box_outline_blank,
        key: Key('completed-icon-$index'),
      ),
    );
  }

  void changeItemCompleteness(Exerciselist item) {
    setState(() {
      item.completed = !item.completed;
    });
  }

  void goToNewItemView() {
    // Here we are pushing the new view into the Navigator stack. By using a
    // MaterialPageRoute we get standard behaviour of a Material app, which will
    // show a back button automatically for each platform on the left top corner
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
      return NewCustomExercise();
    })).then((title) {
      if (title != null) {
        addItem(Exerciselist(title: title));
      }
    });
  }

  void addItem(Exerciselist item) {
    // Insert an item into the top of our list, on index zero
    items.insert(0, item);
    if (animatedListKey.currentState != null)
      animatedListKey.currentState.insertItem(0);
  }

  void goToEditItemView(Exerciselist item) {
    // We re-use the NewTodoView and push it to the Navigator stack just like
    // before, but now we send the title of the item on the class constructor
    // and expect a new title to be returned so that we can edit the item
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
      return NewCustomExercise(item: item);
    })).then((title) {
      if (title != null) {
        editItem(item, title);
      }
    });
  }

  void editItem(Exerciselist item, String title) {
    item.title = title;
  }

  void removeItemFromList(Exerciselist item, int index) {
    animatedListKey.currentState.removeItem(index, (context, animation) {
      return SizedBox(
        width: 0,
        height: 0,
      );
    });
    deleteItem(item);
  }

  void deleteItem(Exerciselist item) {
    // We don't need to search for our item on the list because Dart objects
    // are all uniquely identified by a hashcode. This means we just need to
    // pass our object on the remove method of the list
    items.remove(item);
    if (items.isEmpty) {
      emptyListController.reset();
      setState(() {});
      emptyListController.forward();
    }
  }
}

Exerciselist

class Exerciselist {
  String title;
  bool completed;

  Exerciselist({
    this.title,
    this.completed = false,
  });

  Exerciselist.fromMap(Map<String, dynamic> map)
      : title = map['title'],
        completed = map['completed'];

  updateTitle(title) {
    this.title = title;
  }

  Map toMap() {
    return {
      'title': title,
      'completed': completed,
    };
  }
}

MenuScreen

class MenuScreen extends StatefulWidget {
  @override
  _MenuScreenState createState() => _MenuScreenState();
}

class _MenuScreenState extends State<MenuScreen> {
  int difficulty = 2;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kBackgroundColour,
      appBar: AppBar(
        backgroundColor: kButtonAndBarColour,
        title: Text('COVID-19 WORKOUTS', style: kTitleStyle),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              elevation: 100.0,
              color: kButtonAndBarColour,
              child: Text('CARDIO', style: kTitleStyle),
              onPressed: () {
                //NEED TO UPDATE STATE AND HAVE NEW DATA FOR CARDIO SCREEN
                FeedDifficulty cardioDifficulty =
                    FeedDifficulty(difficulty: difficulty);
                GenerateCardio generateCardio =
                    GenerateCardio(difficulty: difficulty);
                Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => CardioScreen(
                            cardioDifficulty:
                                cardioDifficulty.checkDifficulty(),
                            cardioWorkout1: generateCardio.cExerciseOne(),
                            cardioWorkout2: generateCardio.cExerciseTwo(),
                            cardioWorkout3: generateCardio.cExerciseThree(),
                            cardioWorkout4: generateCardio.cExerciseFour(),
                            cardioWorkout5: generateCardio.cExerciseFive(),
                          )),
                );
                print('Cardio Pressed');
              },
            ),
            SizedBox(
              height: 20.0,
            ),
            RaisedButton(
              elevation: 100.0,
              color: kButtonAndBarColour,
              child: Text(
                'STRENGTH & ENDURANCE',
                style: kTitleStyle,
              ),
              onPressed: () {
                FeedDifficulty strengthWorkout =
                    FeedDifficulty(difficulty: difficulty);
                GenerateStrength generateStrength =
                    GenerateStrength(difficulty: difficulty);
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => StrengthScreen(
                      strengthDifficulty: strengthWorkout.checkDifficulty(),
                      strengthWorkout1: generateStrength.sExerciseOne(),
                      strengthWorkout2: generateStrength.sExerciseTwo(),
                      strengthWorkout3: generateStrength.sExerciseThree(),
                      strengthWorkout4: generateStrength.sExerciseFour(),
                      strengthWorkout5: generateStrength.sExerciseFive(),
                    ),
                  ),
                );
//                Navigator.pushNamed(context, '/strength');
                print('Strength Pressed');
              },
            ),
            RaisedButton(
              elevation: 100.0,
              color: kButtonAndBarColour,
              child: Text(
                'CUSTOM WORKOUT',
                style: kTitleStyle,
              ),
              onPressed: () {
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return CustomExScreen(
                      //construct
                      );
                }));
//                Navigator.pushNamed(context, '/strength');
                print('CUSTOM Pressed');
              },
            ),
            SliderTheme(
              data: SliderTheme.of(context).copyWith(
                inactiveTrackColor: Color(0xFF8D8E98),
                activeTrackColor: Colors.white,
                thumbColor: Color(0xFFEB1555),
                overlayColor: Color(0x29EB1555),
                thumbShape: RoundSliderThumbShape(enabledThumbRadius: 15.0),
                overlayShape: RoundSliderOverlayShape(overlayRadius: 30),
              ),
              child: Slider(
                value: difficulty.toDouble(),
                min: 1.0,
                max: 3.0,
                onChanged: (double newValue) {
                  setState(() {
                    difficulty = newValue.round();
                    print(difficulty);
                  });
                },
              ),
            ),
            Text(
              difficulty.toString(),
              style: kTitleStyleDark,
            ),
            SizedBox(height: 8.0),
            Text(
              'DIFFICULTY',
              style: kTitleStyleDark,
            ),
          ],
        ),
      ),
    );
  }
}

...