'List <dynamic>'유형은 'List <Widget>'유형의 하위 유형이 아닙니다.


85

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>'

여기서 무엇이 잘못 되었습니까?

답변:


184

여기서 문제는 유형 추론이 예기치 않은 방식으로 실패한다는 것입니다. 해결책은 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émi Rousselet 2018

이 특정 변경은 아마도 "흐릿한 화살표"라고도하는 아래쪽으로 동적과 관련이있을 것입니다. 이전에는 List <dynamic>을 List <X>에 할당해도 괜찮 았습니다. 그것은 많은 추론 차이를 덮었습니다.
Jonah Williams

1
TBH 나는 그의 버그를 재현하지 못했습니다. 그의 코드는 List<ListTile>지정하지 않고 짝수 로 추론되기 때문에 map.
Rémi Rousselet

2
그게 문제를 해결했습니다. 하지만 조금 이상하고 다트를 처음 접해서 이해했다고 말할 수 없습니다.
Arash

나는 같은 문제에 직면했다 (그러나 내 시나리오는 달랐다). 이것은 Dart 2의 강력한 유형 때문이라고 생각합니다. 변수 선언을 List <Widget>으로 변경하면 작동하기 시작했습니다.
Manish Kumar

13

동적 목록을 특정 유형의 목록으로 캐스팅 할 수 있습니다.

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

5

나는 다음으로 변환 Map하여 내 문제를 해결 했습니다.Widget

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

간단한 답변 감사합니다!
user3079872

3

나는 당신 이 일부 위젯 의 자식 속성 에서 _buildBody를 사용한다고 생각 하므로 아이들List 위젯 ( 위젯 배열)을 기대 하고 _buildBody는 'List dynamic'을 반환합니다 .

매우 간단한 방법으로 변수를 사용하여 반환 할 수 있습니다.

// 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'.");},
    );
  }
}

동적 위젯 을 사용 하여 화면에 위젯 을 표시하고 숨기는 완전한 예제 를 만들었 습니다. 온라인에서 실행되는 dart fiddle 도 볼 수 있습니다.

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


이것은 더 이상 작동하지 않는 것 같습니다. 예 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_74

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.