Reconstruction de flutter provoquant une modification des données

Sep 28 2020

Je suis un débutant chez Flutter and Dart et j'essaie de créer une application de liste de tâches qui utilise le plugin SQFLite pour conserver les données. J'ai une liste de tâches (objets d'une classe personnalisée) et j'essaie de donner aux utilisateurs la possibilité (via un menu déroulant) de sélectionner une catégorie particulière de tâches - l'ID de catégorie est stocké en tant qu'attribut de la tâche. Lorsque je génère une liste filtrée basée sur des tâches et que j'utilise setState pour définir ma liste de tâches de classe sur cette liste générée, elle se reconstruit simplement sur la liste de classe entière. Je ne peux pas comprendre où cette reconstruction a lieu.

Ma fonction filterTasks qui prend un nom de catégorie, identifie son identifiant de catégorie - le nom de catégorie est `` au cas où l'utilisateur efface le filtre - puis boucle à travers toutes les tâches pour trouver où l'identifiant correspond (je me rends compte que je pourrais le faire avec la base de données également et sélectionnez tout ce qui correspond à l'ID, mais même ce moyen devrait fonctionner) et s'il y a des correspondances, il définit les tâches affichées pour être cette liste filtrée.

void filterTasks(String category) async {
    await updateList(); //gets the entire list
    print('Mid ${this.taskList}'); if (category != '') { int filteredId = await getCategoryId(category); List<Task> filtered = []; int count = taskCount; for (int i = 0; i < count; i++) { if (this.taskList[i].taskCategory == filteredId) { filtered.add(this.taskList[i]); } } if (filtered.isEmpty) { showSnackBar(context, "Error, no tasks of this category exist.", false); setState(() { categoryChoice = null; }); } else { setState(() { this.taskList = filtered; this.taskCount = this.taskList.length; print('End ${this.taskList}');
        });
      }
    }
  }

La fonction de liste de mise à jour récupère simplement la liste complète des tâches et des catégories à partir de la base de données car un utilisateur peut vouloir changer directement entre les filtres et ne pas avoir à nettoyer le filtre. Je l'ai mis en attente car il s'agit d'une fonction asynchrone et j'ai pensé qu'il pourrait remplacer la liste filtrée après l'achèvement de cette fonction filterTasks.

C'est la partie initiale de ma fonction de construction, où j'appelle la liste de mise à jour au cas où la taskList ou la categoryList serait nulle, ce qui n'est pas le cas ici.

Widget build(BuildContext context) {
    print('Start ${this.taskList}');
    if (taskList == null || categoryList == null) {
      taskList = List<Task>();
      categoryList = List<Category>();
      updateList();
    }
    return Scaffold()//my widget tree

Le code du bouton déroulant qui appelle la fonction:

DropdownButton(
            hint: Text(
              'Filter',
              style: TextStyle(
                color: textColor,
              ),
            ),
            dropdownColor: bgColorPrimary,
            value: categoryChoice,//class variable
            items: this.categoryList?.map((Category instance) {
                  return DropdownMenuItem(
                      value: instance.categoryName,
                      child: Text(
                        instance.categoryName,
                        style: TextStyle(
                            color: categoryColorsMap[instance.categoryColour],
                            fontSize: 16.0),
                      ));
                })?.toList() ??
                [],
            onChanged: (newValue) {
              filterTasks(newValue);
            },
            icon: Icon(
              Icons.filter_list,
              color: textColor,
            ),
          )

La liste de filtres est réinitialisée par une autre icône qui se trouve juste après le bouton déroulant qui définit simplement categoryChoice sur null (pour afficher l'indication de la liste déroulante) et appelle les filterTasks avec le paramètre «».

EDIT: Après avoir bricolé quelques instructions d'impression, 4 en particulier, avec 3 affichées dans les extraits de code et une au début de la fonction updateList, je suis maintenant plus intriguée. L'instruction d'impression dans updateList dit simplement `` déclenché '' et la sortie est la suivante:

//APP BOOT UP
I/flutter (18734): Start null
I/flutter (18734): triggered
I/flutter (18734): Start [Instance of 'Task', Instance of 'Task', Instance of 'Task', Instance of 'Task']
//THIS IS WHEN I FILTERED THE TASKS
I/flutter (18734): triggered
I/flutter (18734): mid [Instance of 'Task', Instance of 'Task', Instance of 'Task', Instance of 'Task']
I/flutter (18734): End [Instance of 'Task', Instance of 'Task']
I/flutter (18734): Start [Instance of 'Task', Instance of 'Task']
I/flutter (18734): Start [Instance of 'Task', Instance of 'Task', Instance of 'Task', Instance of 'Task']

Et donc, pendant que la taskList est mise à jour, ce n'est pas la updateList qui la fait revenir à la liste entière. Je ne peux tout simplement pas comprendre ce que fait. Toute aide serait appréciée Merci.

PS Je suis un débutant en fléchettes donc je ne suis pas tout à fait familier avec les conventions de dénomination et les nuances plus fines de la POO, si vous avez des commentaires à ce sujet, faites-le moi savoir :) Merci pour votre aide.

Réponses

Akashvshroff Sep 29 2020 at 13:17

J'ai finalement corrigé l'erreur, et je laisse ceci ici au cas où quelqu'un commettrait des erreurs de débutant comme moi. Le problème résidait dans la updateList comme je le soupçonnais mais plus tard exclu (à ma propre stupidité) et comme la fonction était composée d'instructions alors, attendre que la fonction ne fasse rien et une fois qu'une filteredList a été générée, elle a été rapidement remplacée. liste entière dérivée par updateList. Changer la fonction updateList en asynchrone et utiliser le mot clé await signifiait que la filteredList ne serait générée qu'après la mise à jour de la liste.

ANCIENNE FONCTION:

void updateList() {
    Future<Database> dbFuture = databaseHelper.initialiseDatabase();
    dbFuture.then((database) {
      Future<List<Task>> taskListFuture = databaseHelper.getTaskList();
      taskListFuture.then((taskList) {
        setState(() {
          this.taskList = taskList;
          this.taskCount = taskList.length;
        });
      });

      Future<List<Category>> categoryListFuture =
          databaseHelper.getCategoryList();
      categoryListFuture.then((categoryList) {
        setState(() {
          this.categoryList = categoryList;
          this.categoryCount = categoryList.length;
        });
      });
}

NOUVELLE FONCTION:

 void updateList() async {
    Database db = await databaseHelper.initialiseDatabase();
    List<Task> taskTemp = await databaseHelper.getTaskList();
    List<Category> categoryTemp = await databaseHelper.getCategoryList();
    setState(() {
      this.taskList = taskTemp;
      this.taskCount = taskTemp.length;
      this.categoryList = categoryTemp;
      this.categoryCount = categoryTemp.length;
    });
  }

Cela a corrigé l'erreur de filtrage, j'espère que cela peut aider toute autre personne coincée dans une situation similaire. Merci à tous ceux qui ont essayé de m'aider.