0

I have a flutter app that kind of emulates Reddit. Users can create a Post(title, numdownvotes, numupvotes). Users can also see the posts in a DataTable and visualize the posts data with a flutter_chart. I already have it working with hardcoded values for the posts where there is a List that gets initialized with instances of Post inside it and then the DataTable and flutter_chart use this List to populate themselves. I'm now trying to add sqflite functionality to it and have made some progress. I can add posts to the database, and read them out to the console. I'm struggling with how I can initialize the List<Post?> posts to contain data from the database.

I tried doing it like such in the initState() but get an error: type 'Future' is not a subtype of type 'List?' in type cast

Here's my code: `

@override
void initState(){
  super.initState();
  _posts = model.getAllPosts() as List<Post>?;

  model.insertPost(Post(title: "Coolest Post", numDownVotes: 6, numUpVotes: 9));
  model.insertPost(Post(title: "Nice Post", numDownVotes: 8, numUpVotes: 10));
  model.insertPost(Post(title: "Dope Post", numDownVotes: 2, numUpVotes: 1));
}

`

The model in this case is a class I made that reads from the database: `

Future getAllPosts() async{
  //This needs to be present in any queries, updates, etc.
  //you do with your database
  final db = await DBUtils.init();
  final List maps = await db.query('post_items');
  List result = [];
  for (int i = 0; i < maps.length; i++){
    result.add(
        Post.fromMap(maps[i])
    );
  }
  return result;
}

`

I did some type checking to see what exactly is returned from getAllPosts() and it is a list of Post objects so I'm not being able to understand why my code in initState() does not work? Would be very helpful if someone could provide insight on how I can populate my variable _posts with data from the database.

Code for the DataTable. It uses _posts which is a hardcoded List<Post?>. The DataTable is within a Scaffold():

 body: DataTable(
    sortColumnIndex: sortColumnIndex,
    columns: [
      DataColumn(label: Text("Ttile"), onSort: onSort),
      DataColumn(label: Icon(Icons.arrow_drop_up), onSort: onSort),
      DataColumn(label: Icon(Icons.arrow_drop_down), onSort: onSort)
    ],
    rows:
      _posts!.map(
              (Post post) => DataRow(
                  cells: <DataCell>[
                    DataCell(Text(post.title!.toString())),
                    DataCell(Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Text(post.numUpVotes!.toString()),
                        IconButton(icon: Icon(Icons.arrow_upward), onPressed: () {
                          setState(() {
                            post.numUpVotes = (post.numUpVotes! + 1);
                          });
                        },
                        )
                      ],
                    )
                    ),
                    DataCell(Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Text(post.numDownVotes!.toString()),
                        IconButton(icon: Icon(Icons.arrow_downward), onPressed: () {
                          setState(() {
                            post.numDownVotes = post.numDownVotes! - 1;
                          });
                        },)
                      ],
                    )
                    )
                  ]
              )).toList(),
  • Does this answer your question? [What is a Future and how do I use it?](https://stackoverflow.com/questions/63017280/what-is-a-future-and-how-do-i-use-it) – nvoigt Dec 01 '22 at 22:17
  • So I did try something related to Future. I tried making the initState() a Future function but that didn't work and I didn't really expect it to since it is an initialization call. Maybe I'm still missing something in how Future works exactly? – QuintessentialGamer Dec 01 '22 at 22:21

1 Answers1

1

first set a return type for your _ method:

    Future<List<Post>> getAllPosts() async{ // specify type
  //This needs to be present in any queries, updates, etc.
  //you do with your database
  final db = await DBUtils.init();
  final List maps = await db.query('post_items');
  List<Post> result = []; // specify type
  for (int i = 0; i < maps.length; i++){
    result.add(
        Post.fromMap(maps[i])
    );
  }
  return result;
}

then use this FutureBuilder widget in your UI:

FutureBuilder<List<Post>>(
        future: getAllPosts(),
        builder: (_, AsyncSnapshot<List<Post>> snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          }
          if (snapshot.hasData) {
            final _posts = snapshot.data! as List<Post>;
            print(_posts);

            return DataTable(
              sortColumnIndex: sortColumnIndex,
              columns: [
                DataColumn(label: Text("Ttile"), onSort: onSort),
                DataColumn(
                    label: Icon(Icons.arrow_drop_up), onSort: onSort),
                DataColumn(
                    label: Icon(Icons.arrow_drop_down), onSort: onSort)
              ],
              rows: _posts!
                  .map((Post post) => DataRow(cells: <DataCell>[
                        DataCell(Text(post.title!.toString())),
                        DataCell(Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            Text(post.numUpVotes!.toString()),
                            IconButton(
                              icon: Icon(Icons.arrow_upward),
                              onPressed: () {
                                setState(() {
                                  post.numUpVotes = (post.numUpVotes! + 1);
                                });
                              },
                            )
                          ],
                        )),
                        DataCell(Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            Text(post.numDownVotes!.toString()),
                            IconButton(
                              icon: Icon(Icons.arrow_downward),
                              onPressed: () {
                                setState(() {
                                  post.numDownVotes =
                                      post.numDownVotes! - 1;
                                });
                              },
                            )
                          ],
                        ))
                      ]))
                  .toList(),
            );
          }

          return Text("no data");
        },
      ),
Gwhyyy
  • 7,554
  • 3
  • 8
  • 35
  • remove the getAllPosts() from initState since we don't need it anymore, and use this FutureBuilder in your UI. – Gwhyyy Dec 01 '22 at 23:10
  • Sorry to get back to you so late, I got caught up in other work. But it worked! Just one last thing; if I navigate to the screen where I can add a new post and then come back to the DataTable screen, it doesn't add the post until I reload the app. Any idea on how to tackle this? – QuintessentialGamer Dec 03 '22 at 17:57
  • what state manager do you use! – Gwhyyy Dec 03 '22 at 18:13
  • weel you don't use any, at this point you could surely update the state with a setState() but I don't recommend trying to update the state of a screen from another screen, consider using at least an inherited widget, or choose a state manager option to manage situation like this. – Gwhyyy Dec 03 '22 at 18:17
  • Yes, I do have some setState() functions that I use but they don't seem to work. I think it's because I'm manipulating the data in the final _posts vs. the data stored in the database. You can actually see my setState() functions in the code above. – QuintessentialGamer Dec 03 '22 at 18:19