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(),
2
  • Does this answer your question? What is a Future and how do I use it? Commented Dec 1, 2022 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? Commented Dec 1, 2022 at 22:21

1 Answer 1

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");
        },
      ),
Sign up to request clarification or add additional context in comments.

5 Comments

remove the getAllPosts() from initState since we don't need it anymore, and use this FutureBuilder in your UI.
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?
what state manager do you use!
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.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.