#flutter #dart #recursion #types
Вопрос:
Я пытаюсь сделать некоторые базовые вещи, такие как использование рекурсивной функции для создания древовидного представления на главной странице моего приложения.
Здесь процесс обобщен:
- извлеките всю древовидную структуру из firestore в виде единого документа. Структура документа выглядит следующим образом (псевдо-документ):
{ tree: { total:"3", name:"A name", children[ { total:"4", name:"Another name", children:[ {},... ] }, { total:"5", name:"Main name", children:[ {},... ] }, ] } }
- используйте виджет для анализа структуры полученного документа, а затем отображения дерева. Поскольку я хотел бы управлять некоторыми состояниями внутри каждого уровня (например, открыть/закрыть, ecc), я бы выбрал виджет с отслеживанием состояния (
Levels
). Вот фрагмент кода (без управления состоянием):
class MainPage extends StatelessWidget { const MainPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return StreamBuilderlt;DocumentSnapshotlt;Maplt;String, dynamicgt;gt;gt;( //get doc from firestore! stream: FirebaseFirestore.instance.collection('taxonomy_tree').doc("main_tree").snapshots(), builder:(context, AsyncSnapshotlt;DocumentSnapshotlt;Maplt;String, dynamicgt;gt;gt;snapshot){ if(!snapshot.hasData) return Text("Loading"); else { Maplt;String, dynamicgt;? tree = snapshot.data?.data(); if(tree != null){ return Levels(elements:tree["tree"] as Maplt;String,dynamicgt;,level:0.0);//call Levels Widget } else return Text("No data"); } } ); } } class Levels extends StatefulWidget { Levels({Key? key, required this.elements, required this.level}) : super(key: key); final Maplt;String, dynamicgt; elements; final double level; @override _LevelsState createState() =gt; _LevelsState(); } class _LevelsState extends Statelt;Levelsgt; { @override Widget build(BuildContext context) { Listlt;Maplt;String, dynamicgt;gt; el = widget.elements.containsKey("children") ? widget.elements["children"] as Listlt;Maplt;String, dynamicgt;gt; :[]; return Padding( padding: EdgeInsets.only(left:widget.level*10), child: ListView( children: [ Text(widget.elements["name"] ?? ""), Text(widget.elements["total"]?.toString() ?? "0.0"), //OUCH! el[i] seems to cause an ERROR for (int i = 0; ilt; el.length;i ) Levels(elements:el[i], level: widget.level 1) ] ) ); } }
Когда код пытается вызвать Levels
с аргументом el[i]
, я получаю следующую ошибку:
type 'Listlt;dynamicgt;' is not a subtype of type 'Listlt;Maplt;String, dynamicgt;gt;' in type cast
Я пытался привести el[i]
явно ( el[i] as Maplt;String,dynamicgt;
), но все равно получаю ошибку.
Что я упускаю?
Спасибо
Комментарии:
1. попробуйте создать streambuilder в statefulwidget
2. Hummm…It мне это кажется бессмысленным, но спасибо за комментарий. Я все равно пытался, почему бы и нет, и это не работает
3. Я попросил вас использовать streambuilder для улучшения вашего кода, и это не ответ, так как я его прокомментировал!
Ответ №1:
Это происходит потому, что, когда вы создаете другой объект своего класса Level
, ваше состояние
Listlt;Maplt;String, dynamicgt;gt; el = widget.elements.containsKey("children") ? widget.elements["children"] as Listlt;Maplt;String, dynamicgt;gt; :[];
снова запускается внутри класса объектов
но ваш следующий children
children:[ {},... ]
у него нет никаких данных, что означает, что он вернется
Картаlt;динамичная, динамичнаяgt;
чтобы избавиться от этой проблемы, просто заполните некоторые данные в другой children
части дерева данных, как показано ниже
{ "tree": { "total": "3", "name": "A name", "children": [ { "total": "4", "name": "Another name", "children": [ {"data": 121} ] }, { "total": "5", "name": "Main name", "children": [ {"data1": 4545} ] }, ] } }
Комментарии:
1. Спасибо @Diwyansh, но это не тот случай. Я опубликовал псевдо-json, настоящий json заполнен правильно. Я думаю, что десериализация-это решение здесь. В любом случае, спасибо
2. Я успешно запустил этот код, и он отлично работает после внесения вышеуказанных изменений, поскольку вы создаете объект внутри объекта, вам также необходимо убедиться, что ваше условие containskey верно или нет, также можно прикрепить скриншот необходимого.