'List <dynamic>' türü, 'List <Widget>' türünün bir alt türü değil


94

Firestore örneğinden kopyaladığım bir kod pasajım var:

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(),
        );
      },
    );
  }

Ama bu hatayı alıyorum

type 'List<dynamic>' is not a subtype of type 'List<Widget>'

Burada ters giden ne?

Yanıtlar:


211

Buradaki sorun, tür çıkarımının beklenmedik bir şekilde başarısız olmasıdır. Çözüm, mapyönteme bir tür argümanı sağlamaktır .

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

Daha karmaşık cevap, türü childrenolduğu halde List<Widget>, bu bilginin tekrar çağrıya doğru akmamasıdır map. Bunun nedeni map, ardından gelen toListve kapanışın dönüşünü açıklama yazmanın bir yolu olmadığı için olabilir.


1
Dart 2 kullanılarak güçlü mod veya flutter ile ilgili olabilir.
Rémi Rousselet

Bu belirli değişiklik, muhtemelen alt, yani "bulanık oklar" olarak dinamik ile ilgilidir - daha önce bir List <dynamic> 'i bir List <X>' e atamakta sorun yoktu. Bu, birçok çıkarım boşluğunu kapattı.
Jonah Williams

1
TBH Onun böceğini yeniden üretmeyi başaramadım. Onun kodu, List<ListTile>belirtilmeden bir çift olarak çıkarıldığı için map.
Rémi Rousselet

2
Peki bu sorunu çözdü. Ama biraz tuhaf, dartta yeniyim, bu yüzden gerçekten anladığımı söyleyemem.
Arash

Ben de aynı sorunla karşı karşıyaydım (Ama benim senaryom farklıydı). Bunun Dart 2 güçlü türü yüzünden olduğunu düşünüyorum. Değişken bildirimini List <Widget> olarak değiştirdikten sonra çalışmaya başladı.
Manish Kumar

15

Dinamik Listeyi Belirli Türe Sahip Listeye Yayınlayabilirsiniz:

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

7

Sorunumu Mapşu şekle dönüştürerek çözdüm :Widget

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

Bu kadar basit bir cevap için teşekkür ederim!
user3079872

4

Ben de _buildBody kullanmak olduğunu düşünüyorum çocuklar böylece, bazı widget özellikleri çocukların bir bekliyoruz Liste Widget (Widget dizisi) ve _buildBody bir döner 'Liste dinamik' .

Çok basit bir şekilde, onu döndürmek için bir değişken kullanabilirsiniz:

// 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
)

Örnek ( 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
        )
      )
    );
  }

}

Bir kullanarak diğer bir örnek Widget bir mesafede (oneWidget) Widget'lerle Listesi (arrayOfWidgets). Bir parçacığın (MyButton) bir parçacığı kişiselleştirmek ve kod boyutunu küçültmek için nasıl kapsamının olduğunu gösteriyorum:

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

Ben yapılan eksiksiz bir örnek kullandığım o dinamik widget'lar ekranda göstermek ve gizlemek widget'lara, bunu online çalışan görebilirsiniz dart keman de.

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());
  }
}

Belki birine yardımcı olur. Sizin için yararlı olduysa, lütfen yukarı oku tıklayarak bana bildirin. Teşekkürler.

https://dartpad.dev/b37b08cc25e0ccdba680090e9ef4b3c1


1
Bu artık işe yaramıyor gibi görünüyor. Örneğin atanamıyor Text('My Buttons')içine List<Widget>diziden. Alınıyor The element type 'Text' can't be assigned to the list type 'Widget'. Bunun için geçici çözüm ne olabilir?
shaimo

Metin bir Widget'tır ve List <Widget> öğesinin bir öğesi olabilir. Bu pedi kontrol edin https://dartpad.dev/6a908fe99f604474fd052731d59d059c ve bana işe yarayıp yaramadığını söyleyin.
lynx_74

"'Liste <Widget>' öğe türü, 'Widget' liste türüne atanamaz." ilk örneğinizden. Artık işe yaramıyor gibi görünüyor
Petro

1

Bu benim için çalışıyorList<'YourModel'>.from(_list.where((i) => i.flag == true));


0

Her öğeyi bir widget'a dönüştürmek için ListView.builder () yapıcısını kullanın.

Genel olarak, ne tür bir öğe ile uğraştığınızı kontrol eden ve bu tür öğe için uygun pencere öğesini döndüren bir oluşturucu işlevi sağlayın.

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),
    );
  },
);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.