Home > Back-end >  Elements from webservice doesn't appear in Drag and drop List in Flutter
Elements from webservice doesn't appear in Drag and drop List in Flutter

Time:09-23

I have build a drag and drop list with static data which work well, now when I try to add data from a webservice it doesn't show in the widget (it show only the static data) :

enter image description here

But at the same time when I do a print() of the list in the console it shows all the data (static and from the webservice):

enter image description here

Here is my code :

class Taches extends StatefulWidget{
  @override
  TachesState createState(){
    return new TachesState();
  }
}
class TachesState extends State<Taches> {

  //the static data
  List<String> listeTaches = [
    'Tâche 1',
    'Tâche 2',
    'Tâche 3',
    'Tâche 4',
    'Tâche 5',
    'Tâche 6',
    'Tâche 7',
    'Tâche 8',
    'Tâche 9',
    'Tâche 10',
  ];

  void getTaches() async {
    Session session = new Session();
    var taches = jsonDecode(await session.authentification());
    //here I add the data from the webservice
    for(int i = 0; i < taches['result']["inRangeTasks"].length ; i  ){
      var tacheStr = taches['result']["inRangeTasks"][i]['name'];
      listeTaches.add(tacheStr.toString());
    }
    print(listeTaches);
  }

  _onReorder(oldIndex, newIndex) {
    setState((){
      if(newIndex > oldIndex){
        newIndex -= 1;
      }
      var item = listeTaches.removeAt(oldIndex);
      listeTaches.insert(newIndex, item);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: NavDrawer(),
      appBar: AppBar(
        title: Text('Beotic Project'),
        centerTitle: true,
      ),
      body: ReorderableListView(
            header: Center(
              child: Container(
                child: Text(
                  'Listes des tâches',
                  style: Theme.of(context).textTheme.headline5,
                ),
                padding: EdgeInsets.symmetric(vertical: 20)
              )
            ),
            children: listeTaches.map((e) => ListTile(
                key: UniqueKey(),
                leading: Icon(Icons.task),
                title: Text(e),
                trailing: Icon(Icons.more_vert),
              )).toList(), 
            onReorder: _onReorder,
      ),
    );
  }

  @override
  void initState(){
    //I directly call, in the initState function, the function which extract the data from the webservice and put it in the list
    getTaches();
  }
}

My goal is to make all the data from the list appear on the widget,

May be I'm doing something wrong,

Thanks for helping !

CodePudding user response:

The problem with your code is that although getTaches() is an async function, you can't await it in initState, because initState can't be an async function. As a result your ReorderableListView will be built earlier than the data is returned and added to listeTaches in getTaches() function.

The solution is using a FutureBuilder, and building the widget only after the future (fetching) is completed. Check the following code. I simplified it and simulated a delay and the backend call, but you can see how it works and adjust it to your needs.

import 'package:flutter/material.dart';

void main() => runApp(
      const MaterialApp(
        home: Scaffold(body: Taches()),
      ),
    );

class Taches extends StatefulWidget {
  const Taches({Key? key}) : super(key: key);
  @override
  TachesState createState() => TachesState();
}

class TachesState extends State<Taches> {
  //the static data
  List<String> listeTaches = [
    'Tâche 1',
    'Tâche 2',
    'Tâche 3',
    'Tâche 4',
    'Tâche 5',
    'Tâche 6',
    'Tâche 7',
    'Tâche 8',
    'Tâche 9',
    'Tâche 10',
  ];

  Future<List<String>> getTaches() async {
    return Future.delayed(const Duration(milliseconds: 2000), () {
      for (int i = 11; i <= 20; i  ) {
        listeTaches.add('Tâche $i');
      }
      return listeTaches;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
            child: FutureBuilder<List<String>>(
                future:
                    getTaches(), // a previously-obtained Future<String> or null
                builder: (BuildContext context,
                    AsyncSnapshot<List<String>> snapshot) {
                  if (snapshot.hasError) {
                    // manage error
                    return const Text('Error');
                  }
                  // no error and we have data
                  if (snapshot.hasData) {
                    return ReorderableListView(
                      header: Center(
                          child: Text(
                        'Listes des tâches',
                        style: Theme.of(context).textTheme.headline5,
                      )),
                      children: listeTaches
                          .map((e) => ListTile(
                                key: UniqueKey(),
                                leading: const Icon(Icons.task),
                                title: Text(e),
                                trailing: const Icon(Icons.more_vert),
                              ))
                          .toList(),
                      onReorder: (oldIndex, newIndex) => {},
                    );
                  }
                  // show initial data while loading
                  return const Center(child: CircularProgressIndicator());
                })));
  }
}

  • Related