Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
221 views
in Technique[技术] by (71.8m points)

flutter - Why isn't Navigator.pop() refreshing data?

Hi guys I'm trying to build an app with flutter, so I have two screens HomeScreen() and RoutineScreen(). The first one is a Scaffold and in the body has a child Widget (a ListView called RoutinesWidget()) with all the routines. And the second one is to create a routine. The thing is, that when I create the routine, I use a button to pop to the HomeScreen() but it doesn't refresh the ListView (I'm guessing that it's because when I use Navigator.pop() it refreshes the Scaffold but not the child Widget maybe?)

HomeScreen() code here:

import 'package:flutter/material.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Widgets/routines_widget.dart';
import 'package:workout_time/Widgets/statistics_widget.dart';
import 'package:workout_time/Screens/settings_screen.dart';
import 'package:workout_time/Screens/routine_screen.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  int _selectedIndex = 0;

  List<Widget> _views = [
    RoutinesWidget(),
    StatisticsWidget(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: kThirdColor,
      appBar: AppBar(
        leading: Icon(Icons.adb),
        title: Text("Workout Time"),
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.settings),
              onPressed: () => Navigator.push(context,
                  MaterialPageRoute(builder: (context) => SettingsScreen()))),
        ],
      ),
      body: _views[_selectedIndex],
      floatingActionButton: (_selectedIndex == 1)
          ? null
          : FloatingActionButton(
              onPressed: () async {
                await Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => RoutineScreen(null)));
                setState(() {});
              },
              child: Icon(
                Icons.add,
                color: kSecondColor,
                size: 30.0,
              ),
              elevation: 15.0,
            ),
      bottomNavigationBar: BottomNavigationBar(
        items: <BottomNavigationBarItem>[
          bottomItems(Icon(Icons.fitness_center_rounded), "Routines"),
          bottomItems(Icon(Icons.leaderboard_rounded), "Statistics"),
        ],
        currentIndex: _selectedIndex,
        onTap: (int index) => setState(() => _selectedIndex = index),
      ),
    );
  }
}

BottomNavigationBarItem bottomItems(Icon icon, String label) {
  return BottomNavigationBarItem(
    icon: icon,
    label: label,
  );
}

RoutinesWidget() code here:

import 'package:flutter/material.dart';
import 'package:workout_time/Services/db_crud_service.dart';
import 'package:workout_time/Screens/routine_screen.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Models/routine_model.dart';

class RoutinesWidget extends StatefulWidget {
  @override
  _RoutinesWidgetState createState() => _RoutinesWidgetState();
}

class _RoutinesWidgetState extends State<RoutinesWidget> {
  DBCRUDService helper;

  @override
  void initState() {
    super.initState();
    helper = DBCRUDService();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: helper.getRoutines(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.hasData) {
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (BuildContext context, int index) {
              Routine routine = Routine.fromMap(snapshot.data[index]);
              return Card(
                margin: EdgeInsets.all(1.0),
                child: ListTile(
                  leading: CircleAvatar(
                    child: Text(
                      routine.name[0],
                      style: TextStyle(
                          color: kThirdOppositeColor,
                          fontWeight: FontWeight.bold),
                    ),
                    backgroundColor: kAccentColor,
                  ),
                  title: Text(routine.name),
                  subtitle: Text(routine.exercises.join(",")),
                  trailing: IconButton(
                    icon: Icon(Icons.delete_rounded),
                    color: Colors.redAccent,
                    onPressed: () {
                      setState(() {
                        helper.deleteRoutine(routine.id);
                      });
                    },
                  ),
                  onTap: () => Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => RoutineScreen(routine))),
                ),
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20.0)),
                color: kSecondColor,
              );
            },
          );
        } else {
          return Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}

RoutineScreen() code here:

import 'package:flutter/material.dart';
import 'package:workout_time/Models/routine_model.dart';
import 'package:workout_time/Widgets/type_card_widget.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Services/db_crud_service.dart';

class RoutineScreen extends StatefulWidget {
  final Routine _routine;

  RoutineScreen(this._routine);

  @override
  _RoutineScreenState createState() => _RoutineScreenState();
}

class _RoutineScreenState extends State<RoutineScreen> {
  DBCRUDService helper;

  final _nameController = TextEditingController();

  final _descriptionController = TextEditingController();

  bool _type = true;

  int _cycles = 1;

  int _restBetweenExercises = 15;

  int _restBetweenCycles = 60;

  @override
  void initState() {
    super.initState();
    helper = DBCRUDService();
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.arrow_back),
            onPressed: () => Navigator.pop(context),
          ),
          title: widget._routine != null
              ? Text(widget._routine.name)
              : Text("Create your routine"),
          actions: [
            IconButton(
              icon: Icon(Icons.done_rounded),
              onPressed: createRoutine,
            )
          ],
          bottom: TabBar(
            tabs: [
              Tab(
                text: "Configuration",
              ),
              Tab(
                text: "Exercises",
              ),
            ],
          ),
        ),
        body: TabBarView(children: [
          //_routine == null ? ConfigurationNewRoutine() : Text("WIDGET N° 1"),
          ListView(
            children: [
              Container(
                padding: EdgeInsets.all(15.0),
                child: Row(
                  children: [
                    Text(
                      "Name:",
                      style: TextStyle(
                        fontSize: 20.0,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(
                      width: 40.0,
                    ),
                    Expanded(
                      child: TextField(
                        textAlign: TextAlign.center,
                        controller: _nameController,
                      ),
                    ),
                  ],
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              Card(
                margin: EdgeInsets.all(15.0),
                color: kSecondColor,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(20.0),
                ),
                child: Container(
                  padding: EdgeInsets.all(15.0),
                  child: Column(
                    children: [
                      Text(
                        "Type",
                        style: TextStyle(fontSize: 25.0),
                      ),
                      Row(
                        children: [
                          Expanded(
                            child: TypeCard(
                              Icons.double_arrow_rounded,
                              _type == true ? kFirstColor : kThirdColor,
                              () => setState(() => _type = true),
                              "Straight set",
                            ),
                          ),
                          Expanded(
                            child: TypeCard(
                              Icons.replay_rounded,
                              _type == false ? kFirstColor : kThirdColor,
                              () => setState(() => _type = false),
                              "Cycle",
                            ),
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              Container(
                padding: EdgeInsets.all(15.0),
                child: Row(
                  children: [
                    Text(
                      "N° cycles:",
                      style: TextStyle(
                        fontSize: 20.0,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(
                      width: 40.0,
                    ),
                    Expanded(
                      child: Text("Hello"),
                    ),
                  ],
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
            ],
          ),
          Text("WIDGET N° 2"),
        ]),
      ),
    );
  }

  void createRoutine() {
    List<String> _exercises = ["1", "2"];
    List<String> _types = ["t", "r"];
    List<String> _quantities = ["30", "20"];

    Routine routine = Routine({
      'name': _nameController.text,
      'description': "_description",
      'type': _type.toString(),
      'cycles': 1,
      'numberExercises': 2,
      'restBetweenExercises': 15,
      'restBetweenCycles': 60,
      'exercises': _exercises,
      'types': _types,
      'quantities': _quantities,
    });
    setState(() {
      helper.createRoutine(routine);
      Navigator.pop(context);
    });
  }
}

Any idea what can I do to make it work? Thank you

question from:https://stackoverflow.com/questions/65926055/why-isnt-navigator-pop-refreshing-data

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

When you push a new Route, the old one still stays in the stack. The new route just overlaps the old one and forms like a layer above the old one. Then when you pop the new route, it will just remove the layer(new route) and the old route will be displayed as it was before.

Now you must be aware the Navigator.push() is an asynchronous method and returns a Future. How it works is basically when you perform a Navigator.push(), it will push the new route and will wait for it to be popped out. Then when the new route is popped, it returns a value to the old one and that when the future callback will be executed.

Hence the solution you are looking for is add a future callback like this after your Navigator.push() :

Navigator.push(context,
                  MaterialPageRoute(builder: (context) => SettingsScreen())
).then((value){setState(() {});});   /// A callback which is executed after the new route will be popped. In that callback, you simply call a setState and refresh the page.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...