У меня есть фрагмент кода, который я скопировал из примера Firestore:

Widget _buildBody(BuildContext context) {
    return new StreamBuilder(
      stream: _getEventStream(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) return new Text('Loading...');
        return new ListView(
          children: snapshot.data.documents.map((document) {
            return new ListTile(
              title: new Text(document['name']),
              subtitle: new Text("Class"),
            );
          }).toList(),
        );
      },
    );
  }

а вот такая ошибка

type 'List' is not a subtype of type 'List'

Что здесь не так?

Ответы (9)

Проблема здесь в том, что выведение типа неожиданно завершается с ошибкой. Решение состоит в том, чтобы предоставить аргумент типа методу map.

snapshot.data.documents.map((document) {
  return new ListTile(
    title: new Text(document['name']),
    subtitle: new Text("Class"),
  );
}).toList()

Более сложный ответ заключается в том, что, хотя типом children является List , эта информация не возвращается к вызову map. Это может быть связано с тем, что за map следует toList, а также из-за того, что нет возможности ввести аннотирование возврата закрытия.

изменение в список путем добавления .toList () устранило проблему

Это работает для меняList <'YourModel'>. From (_list.where ((i) => i.flag == true));

Вы можете преобразовать динамический список в список с определенным типом:

List<'YourModel'>.from(_list.where((i) => i.flag == true));

Чтобы преобразовать каждый элемент в виджет, используйте конструктор ListView.builder ().

В общем, предоставьте функцию построения, которая проверяет, с каким типом элемента вы имеете дело, и возвращает соответствующий виджет для этого типа элемента.

ListView.builder(
  // Let the ListView know how many items it needs to build.
  itemCount: items.length,
  // Provide a builder function. This is where the magic happens.
  // Convert each item into a widget based on the type of item it is.
  itemBuilder: (context, index) {
    final item = items[index];

    return ListTile(
      title: item.buildTitle(context),
      subtitle: item.buildSubtitle(context),
    );
  },
);

У меня был список строк в firestore, который я пытался прочитать в своем приложении. Я получил ту же ошибку, когда попытался преобразовать ее в список строк.

type 'List' is not a subtype of type 'List'

Мне помогло это решение. Проверьте это.

var array = document ['array']; // массив теперь List 
List  strings = List  .from (массив);

Был комментарий об объявлении вашего списка с помощью Вместо «List myList = [1,2,3]»

Объявить в "List" <"Widget"> "myList [1,2,3]"

Можно подтвердить, что это решает ошибку типа «Список» не является подтипом типа «Список»

Я решил свою проблему, преобразовав Map в Widget

      children: snapshot.map((data) => 
               _buildListItem(context, data)).toList(),

Я думаю, что вы используете _buildBody в свойствах children некоторого виджета, поэтому children ожидает List Widget (массив виджетов), а _buildBody возвращает'Динамический список'.

Очень просто, вы можете использовать переменную для его возврата:

// you can build your List of Widget's like you need
List widgets = [
  Text('Line 1'),
  Text('Line 2'),
  Text('Line 3'),
];

// you can use it like this
Column(
  children: widgets
)

Пример (flutter create test1; cd test1; edit lib / main.dart; flutter run):

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  List widgets = [
    Text('Line 1'),
    Text('Line 2'),
    Text('Line 3'),
  ];

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("List of Widgets Example")),
        body: Column(
          children: widgets
        )
      )
    );
  }

}

Другой пример использования Widget (oneWidget) в Списке виджетов(arrayOfWidgets). Я показываю, как расширяется виджет (MyButton) для персонализации виджета и уменьшения размера кода:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  List arrayOfWidgets = [
    Text('My Buttons'),
    MyButton('Button 1'),
    MyButton('Button 2'),
    MyButton('Button 3'),
  ];

  Widget oneWidget(List _lw) { return Column(children: _lw); }

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Widget with a List of Widget's Example")),
        body: oneWidget(arrayOfWidgets)
      )
    );
  }

}

class MyButton extends StatelessWidget {
  final String text;

  MyButton(this.text);

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      color: Colors.red,
      child: Text(text),
      onPressed: (){print("Pressed button '$text'.");},
    );
  }
}

Я сделал полный пример, в котором я использую динамические виджеты для отображения и скрытия виджетов на экране, вы также можете увидеть, как он работает онлайн на скрипке dart.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
  List item = [
    {"title": "Button One", "color": 50},
    {"title": "Button Two", "color": 100},
    {"title": "Button Three", "color": 200},
    {"title": "No show", "color": 0, "hide": '1'},
  ];

  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Dynamic Widget - List"),backgroundColor: Colors.blue),
        body: Column(
          children: [
            Center(child: buttonBar()),
            Text('Click the buttons to hide it'),
          ]
        )
      )
    );
  }

  Widget buttonBar() {
    return Column(
      children: item.where((e) => e['hide'] != '1').map((document) {
        return new FlatButton(
          child: new Text(document['title']),
          color: Color.fromARGB(document['color'], 0, 100, 0),
          onPressed: () {
            setState(() {
              print("click on ${document['title']} lets hide it");
              final tile = item.firstWhere((e) => e['title'] == document['title']);
              tile['hide'] = '1';
            });
          },
        );
      }
    ).toList());
  }
}

Может кому поможет. Если вам это было полезно, дайте мне знать, нажав на стрелку вверх, пожалуйста. Спасибо.

https://dartpad.dev/b37b08cc25e0ccdba680090e9ef4b3c1

2022 WebDevInsider