Результат запроса Mysql в виджетах Flutter

#mysql #node.js #flutter #dart

Вопрос:

Пытаюсь отобразить в Flutter результат, который я получаю от своего узла.JS-сервер с помощью запроса MySQL:

 [{"NAME":"Matematicas"},
{"NAME":"Naturales"},
{"NAME":"Ciencias Sociales"},
{"NAME":"Lenguaje"},
{"NAME":"Religion"}]
 

Это класс, который я использую в Flutter для его обработки:

 class Subject {
  final String name;

  Subject({
    required this.name,
  });

  factory Subject.fromJson(Map<String, dynamic> json) {
    return Subject(name: json['NAME']);
  }
}
 

Это метод, с помощью которого я получаю данные:

 Future<Subject> fetchSubject() async {
  var prefs = await SharedPreferences.getInstance();
  var token = prefs.getString('token');
  var response = await http.get(Uri.parse('http://localhost:8000/subjects'),
      headers: {'x-access-token': token!});

  print(response.body);
  return Subject.fromJson(jsonDecode(response.body));
}
 

Это мое первоначальное состояние

 void initState() {
    super.initState();
    futureSubject = fetchSubject();
  }
 

Это моя часть сборки виджета:

 Widget build(BuildContext context) {
    return FutureBuilder<Subject>(
        future: fetchSubject(),
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            return const Center(
              child: Text('Error'),
            );
          } else if (snapshot.hasData) {
            return Scaffold(
                appBar: AppBar(
                  title: Text('Materias'),
                  backgroundColor: Colors.green[300],
                  actions: [
                    Padding(
                      padding: EdgeInsets.only(right: 3.0),
                      child: IconButton(
                        icon: Icon(Icons.logout),
                        //TODO llamar funcion logout
                        onPressed: () {},
                        iconSize: 26,
                      ),
                    )
                  ],
                ),
                body: Text(snapshot.data!.name));
          } else {
            return const Center(
              child: CircularProgressIndicator(),
            );
          }
        });
  }
 

Вот что я получаю:

 Uncaught (in promise) Error: Expected a value of type 'Map<String, dynamic>', but got one of type 'List<dynamic>'
 

Я просто хочу отобразить информацию, которую я получаю, в виде списка или таблицы, как в моде. Есть какие-нибудь идеи о том, что и как это реорганизовать?

Ответ №1:

Это произошло потому, что ваши возвращаемые данные представляют собой массив. Попробуй это

  final data = json.decode(response.body);
 return List<Subject>.from(data.map((value) => Subject.fromJson(value)));
 

Комментарии:

1. С этим я, наконец, очень близок, только что получил это изображение: [Instance of 'Subject', Instance of 'Subject', Instance of 'Subject', Instance of 'Subject', Instance of 'Subject']

2. Да, это потому, что каждый из них является объектом. В разделе snapshot.hasData создайте новый List<Subject> и сохраните snapshot.data его. Чтобы отобразить все данные, используйте ListView

3. Да, это наконец сработало, спасибо!

Ответ №2:

Похоже fetchSubject , что необходимо изменить метод и сам виджет. Отображаемые вами данные представляют собой список объектов, поэтому ошибка, из которой вы пытаетесь просмотреть тип Map<String, dynamic> , jsonDecode(response.body) но вместо этого она возвращает a List<dynamic> . Таким образом, вам нужно изменить fetchSubject и получить List<Subject из вашего API не просто объект. Или вам нужно обновить API. Просто в качестве примера (не тестировал, но должен работать):

 Future<List<Subject>> fetchSubject() async {
  var prefs = await SharedPreferences.getInstance();
  var token = prefs.getString('token');
  var response = await http.get(Uri.parse('http://localhost:8000/subjects'),
      headers: {'x-access-token': token!});

  print(response.body);
  return jsonDecode(response.body).map((item) => Subject.fromJson(item));
}
 

и измените всю логику, чтобы справиться List Subject с проблемой, а не просто Subject . JSON, возвращаемый вашим API, представляет собой список (массив) объектов, а не просто объект.

Комментарии:

1. Есть ошибка: Expected a value of type 'FutureOr<List<Subject>>', but got one of type 'MappedListIterable<dynamic, dynamic>'