简体   繁体   中英

After saving formfield input to an sqflite DB, the entry doesn't show on the overview screen. It does show after hot reload

ello folks,

I am rather new to Flutter, but eager to learn, and I would be genuinely grateful for a solution or advise. The code is partially stitched together, partially my own.

I'm working on a simplified diary, with a standard couple of standard questions to fill in.

Basic layout

  • opening screen with floating action button to write a new entry. This page also shows previous entries with a future Listviewbuilder.

  • add entry screen with textfields. Upon saving an entry, or editing an update, the user will go back to the opening screen. However, new entries are not shown, nor are updates to previous entries, until I hit hot reload.

My guess (made with rather limited -if we can call it that- experience) is i'm missing something with the state management. The code looks horrible, and there are a million things I like to do to make it shorter, and more succinct. However, firstly I like to get it to function properly.

code for add entry screen:

class AddCircleScreen extends StatefulWidget {
  static const routeName = '/AddCircleScreen';
  final Circle circle;

  const AddCircleScreen({Key key, this.circle}) : super(key: key);

  @override
  _AddCircleScreenState createState() => _AddCircleScreenState(circle);
}

//TODO: Refactor widgets below
class _AddCircleScreenState extends State<AddCircleScreen> {
  Circle circle;
  final gebeurtenisTextController = TextEditingController();
  final gevoelTextController = TextEditingController();
  final gedachtenTextController = TextEditingController();
  final gedragTextController = TextEditingController();
  final gevolgTextController = TextEditingController();
  final toelichtingTextController = TextEditingController();

  _AddCircleScreenState(this.circle);

  @override
  void initState() {
    super.initState();
    if (circle != null) {
      gebeurtenisTextController.text = circle.gebeurtenis;
      gevoelTextController.text = circle.gevoel;
      gedachtenTextController.text = circle.gedachten;
      gedragTextController.text = circle.gedrag;
      gevolgTextController.text = circle.gevolg;
      toelichtingTextController.text = circle.toelichting;
    }
  }

  @override
  void dispose() {
    super.dispose();
    gebeurtenisTextController.dispose();
    gevoelTextController.dispose();
    gedachtenTextController.dispose();
    gedragTextController.dispose();
    gevolgTextController.dispose();
    toelichtingTextController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: (Colors.yellow[100]),
      appBar: AppBar(
        backgroundColor: (Colors.green[400]),
        title: Center(
          child: Text('Small steps...'),
        ),
      ),
      body: SafeArea(
        child: ListView(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(12.0),
              child: TextField(
                decoration: InputDecoration(
                    labelText: 'Gebeurtenis',
                    border: OutlineInputBorder(),
                    hintText: 'Beschrijf kort de situatie'),
                controller: gebeurtenisTextController,
              ),
            ),
          The above code times 6, for all the different textfields.
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
          backgroundColor: Theme.of(context).primaryColor,
          child: Icon(Icons.check),
          onPressed: () async {
            _saveCircle(
              gebeurtenisTextController.text,
              gevoelTextController.text,
              gedachtenTextController.text,
              gedragTextController.text,
              gevolgTextController.text,
              toelichtingTextController.text,
            );
            setState(() {});
          }),
    );
  }

  _saveCircle(String gebeurtenis, String gevoel, String gedachten,
      String gedrag, String gevolg, String toelichting) async {
    if (circle == null) {
      DatabaseHelper.instance.insertCircle(Circle(
          gebeurtenis: gebeurtenisTextController.text,
          gevoel: gevoelTextController.text,
          gedachten: gedachtenTextController.text,
          gedrag: gedragTextController.text,
          gevolg: gevolgTextController.text,
          toelichting: toelichtingTextController.text));
      Navigator.pop(context);
    } else {
      await DatabaseHelper.instance.updateCircle(Circle(
          id: circle.id,
          gebeurtenis: gebeurtenis,
          gevoel: gevoel,
          gedachten: gedachten,
          gedrag: gedrag,
          gevolg: gevolg,
          toelichting: toelichting));
      Navigator.pop(context);
    }
  }
}

code for opening screen:

class CircleOverviewScreen extends StatefulWidget {

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

class _CircleOverviewScreenState extends State<CircleOverviewScreen> {

  @override

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Cirkels'),
      ),
      body: FutureBuilder<List<Circle>>(
        future: DatabaseHelper.instance.retrieveCircles(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data.length,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  title: Text(snapshot.data[index].gebeurtenis),
                  leading: Text(snapshot.data[index].id.toString()),
                  subtitle: Text(snapshot.data[index].gevolg),
                  onTap: () =>
                      _navigateToAddCircleScreen(context, snapshot.data[index]),
                  trailing: IconButton(
                      alignment: Alignment.center,
                      icon: Icon(Icons.delete),
                      onPressed: () async {
                        _deleteTodo(snapshot.data[index]);
                        setState(() {});
                      }),
                );
              },
            );
          } else if (snapshot.hasError) {
            return Center(child: Text("Je hebt nog geen 5G'tjes opgeslagen"));
          }
          return Center(child: CircularProgressIndicator());
        },
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: Theme.of(context).primaryColor,
        child: Icon(Icons.create_sharp),
        onPressed: () => Navigator.push(
          context,
          MaterialPageRoute(
            builder: (_) => AddCircleScreen(),
          ),
        ),
      ),
    );
  }
}

_deleteTodo(Circle circle) {
  DatabaseHelper.instance.deleteCircle(circle.id);
}

_navigateToAddCircleScreen(BuildContext context, Circle circle) async {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => AddCircleScreen(circle: circle)),
  );
}

A simple way to refresh you screen is to call setState() when the AddCircle screen is popped. You can do this when the Future returned by Navigator.push() completes.

onPressed: () => Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => AddCircleScreen(),
  ),
).then((_) => setState(() {})),

In the long run you should learn to use A StreamBuilder widget and proper state management to solve this kind of problem.

I'm sure you'll enjoy working with apps this way!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM