タイプ「List <dynamic>」はタイプ「List <Widget>」のサブタイプではありません


94

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<dynamic>' is not a subtype of type 'List<Widget>'

ここで何が問題になっていますか?

回答:


211

ここでの問題は、型推論が予期しない方法で失敗することです。解決策は、mapメソッドに型引数を提供することです。

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

より複雑な答えは、のタイプはchildrenですがList<Widget>、その情報はmap呼び出しに逆流しないということです。これmapは、その後に続くため、toListおよびクロージャの戻りに注釈を付けるタイプがないためである可能性があります。


1
Dart 2を使用したスト​​ロングモードまたはフラッターに関連している可能性があります。
RémiRousselet 2018

この特定の変更は、おそらく「ファジー矢印」として知られる動的に関連しています。以前は、List <dynamic>をList <X>に割り当てても問題ありませんでした。それは多くの推論のギャップを埋めました。
ジョナウィリアムズ

1
TBH私は彼のバグを再現することができませんでした。彼のコードは、List<ListTile>に指定しなくても偶数として推測されるためmapです。
レミRousselet

2
それで問題は解決しました。でもちょっと不思議で、ダーツは初めてなので、理解できたとは言えません。
Arash

私は同じ問題に直面していました(しかし、私のシナリオは異なっていました)。これはダート2ストロングタイプのせいだと思います。変数宣言をList <Widget>に変更すると、機能し始めました。
マニッシュクマール

15

動的リストを特定のタイプのリストにキャストできます。

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


4

一部のウィジェットのプロパティで_buildBodyを使用していると思います。そのため、リストウィジェットウィジェットの配列)を期待し、_buildBodyは「リストダイナミック」を返します。

非常に簡単な方法で、変数を使用してそれを返すことができます。

// you can build your List of Widget's like you need
List<Widget> 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<MyApp> {
  List<Widget> 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
        )
      )
    );
  }

}

ウィジェットのリスト(arrayOfWidgets)内でウィジェット(oneWidget)を使用する別の例。ウィジェット(MyButton)がウィジェットをパーソナライズし、コードのサイズを縮小する方法を示します。

import 'package:flutter/material.dart';

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

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

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

  Widget oneWidget(List<Widget> _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'.");},
    );
  }
}

私は完全な例を作りました動的ウィジェットを使用して画面上でウィジェットを表示および非表示にする。ダートフィドルでもオンラインで実行されているのを確認できます。

import 'package:flutter/material.dart';

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

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

class _MyAppState extends State<MyApp> {
  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<Widget>"),backgroundColor: Colors.blue),
        body: Column(
          children: <Widget>[
            Center(child: buttonBar()),
            Text('Click the buttons to hide it'),
          ]
        )
      )
    );
  }

  Widget buttonBar() {
    return Column(
      children: item.where((e) => e['hide'] != '1').map<Widget>((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


1
これはもはや機能していないようです。たとえばText('My Buttons')List<Widget>配列に割り当てることはできません。取得The element type 'Text' can't be assigned to the list type 'Widget'。これの回避策は何でしょうか?
shaimo

テキストはウィジェットであり、List <Widget>の要素にすることができます。このパッドhttps://dartpad.dev/6a908fe99f604474fd052731d59d059cを確認して、問題がないか教えてください。
lynx_ 7420

「要素タイプ 'List <Widget>'をリストタイプ 'Widget'に割り当てることはできません。」あなたの最初の例から。もう機能していないようです
Petro

1

これは私のために働きますList<'YourModel'>.from(_list.where((i) => i.flag == true));


0

各アイテムをウィジェットに変換するには、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),
    );
  },
);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.