Flutter类型'Future <dynamic>'不是'Widget'类型错误的子类型

时间:2020-11-04 22:22:06

标签: flutter flutter-alertdialog

我在具有流构建器的flutter项目中添加了一个弹出窗口(alertdialog)。起初它没有用,但是在使其异步并添加如下代码之后

await Future.delayed(Duration(milliseconds: 50));

它开始正常工作。在数据库中的特定数据更改后,将发生此弹出窗口。后来我想向我的项目中添加第二个弹出窗口以获取第二个数据库值,不同之处在于该窗口有一个用于用户输入的文本字段,而在此之外则是一个控制器。当我尝试使用此弹出窗口时,效果很好,但在弹出窗口的后面给出了

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

错误,带有红色/黄色错误背景。这两个弹出窗口之间的区别在于,我说其中一个具有输入控制器,我在这里做错了什么?

这是完整的代码:

   import 'dart:math';
    
    import 'package:flutter/material.dart';
    import 'package:assets_audio_player/assets_audio_player.dart';
    import 'package:flutter/scheduler.dart';
    import 'numbers.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:firebase_core/firebase_core.dart';
    import 'package:sayi_avi/homescreen.dart';
    
    
    Numbers myNumbers = Numbers();
    
    void main(){
      runApp(
          GameScreen()
      );
    }
    
    class GameScreen extends StatefulWidget {
      static String id ='gamescreen';
    
      @override
      _GameScreenState createState() => _GameScreenState();
    }
    
    class _GameScreenState extends State<GameScreen> {
      bool _initialized = false;
      bool _error = false;
      TextEditingController _controller;
    
      void initializeFlutterFire() async {
        try {
          // Wait for Firebase to initialize and set `_initialized` state to true
          await Firebase.initializeApp();
          setState(() {
            _initialized = true;
          });
        } catch(e) {
          // Set `_error` state to true if Firebase initialization fails
          setState(() {
            _error = true;
          });
        }
      }
    
      @override
      void initState() {
        initializeFlutterFire();
        super.initState();
        getCurrentUser();
        _controller = TextEditingController();
      }
    
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      final _auth =FirebaseAuth.instance;
      User loggedInUser;
      final _firestore = FirebaseFirestore.instance;
      final String collectionPath = 'users';
      String docPath;
      var userPath;
      DocumentReference userdoc;
      var userSnapshot;
      String gameResult;
      String sendednumber='';
      List<dynamic> kullanicisayilari = [];
      List<dynamic> rakipsayilari = [];
      List<dynamic> sonuc = [];
    
    
      void getCurrentUser() async{
        try{
          final user = await _auth.currentUser;
          if(user !=null){
            loggedInUser =user;
            docPath = loggedInUser.uid;
            userPath = _firestore.collection(collectionPath);
            userdoc = userPath.doc(docPath);
            userSnapshot = userdoc.snapshots();
          }
        }catch(e){
          print(e);
        }
      }
    
      Expanded attachNumber(number,imagenumber){
        return Expanded(
          child:FlatButton(
            onPressed: (){
              setState(() {
                if(!myNumbers.numberStatus[1]){
                  myNumbers.buttonValues['numberimage1'] = imagenumber;
                  myNumbers.numberStatus[1] =true;
                  myNumbers.decimals[1]=number;
                }else if(!myNumbers.numberStatus[2]){
                  myNumbers.buttonValues['numberimage2'] = imagenumber;
                  myNumbers.numberStatus[2] =true;
                  myNumbers.decimals[2]=number;
                }else if(!myNumbers.numberStatus[3]){
                  myNumbers.buttonValues['numberimage3'] = imagenumber;
                  myNumbers.numberStatus[3] =true;
                  myNumbers.decimals[3]=number;
                }else if(!myNumbers.numberStatus[4]){
                  myNumbers.buttonValues['numberimage4'] = imagenumber;
                  myNumbers.numberStatus[4] =true;
                  myNumbers.decimals[4]=number;
                }
              });
              final assetsAudioPlayer = AssetsAudioPlayer();
              assetsAudioPlayer.open(
                Audio("assets/audios/click.wav"),
              );
            },
            padding: EdgeInsets.all(0),
            child: Image.asset('images/$imagenumber'),
          ),
        );
      }
    
      Expanded showDeleteNumbers(statusNumber,number){
        return Expanded(
            child:FlatButton(
              onPressed: (){
                setState(() {
                  myNumbers.decimals[statusNumber]='';
                  myNumbers.numberStatus[statusNumber] =false;
                  myNumbers.buttonValues[number] = 'nonumber.png';
                });
              },
            child: Image.asset('images/'+myNumbers.buttonValues['$number']),
            ),
        );
      }
    
      Future<void> sendnumber() {
        sendednumber="";
        for (var numbers in myNumbers.decimals.values){
          sendednumber = sendednumber+numbers;
        }
        Random rnd;
        int min = 10000;
        int max = 100000;
        rnd = new Random();
        var r = min + rnd.nextInt(max - min);
        kullanicisayilari.add(sendednumber+"|"+r.toString());
        return userPath
            .doc(docPath)
            .update({'atilansayi': kullanicisayilari})
            .then((value) => print("User Updated"))
            .catchError((error) => print("Failed to update user: $error"));
      }
      /*
      List<Widget> getUserNumbers(){
        return
      }
    
       */
    
      Text getUserNumbers(kullanicisayilari){
        for(var number in kullanicisayilari){
        return Text(number);
          };
      }
    

//This one is working fine


      _showMaterialDialog(String type) async{
        if(type=="win"){
          gameResult = "You Win, Gratz!";
        }else if(type=="lose"){
          gameResult = "You Lose :(";
        }
        print("buraya girdi");
        print(gameResult);
        await Future.delayed(Duration(milliseconds: 50));
        showDialog (
            context: context,
            builder: (_) => AlertDialog(
              title: Text("Result"),
              content: Text(gameResult),
              actions: <Widget>[
                FlatButton(
                  child: Text('Close'),
                  onPressed: () {
                      Navigator.pushNamed(context, HomeScreen.id);
                  },
                )
              ],
            ));
      }

//This one is causing errors



      _showMaterialDialogNumber() async{
        await Future.delayed(Duration(milliseconds: 100));
        showDialog (
            context: context,
            builder: (_) => AlertDialog(
              title: Text("Start"),
              content: TextField(
                controller: _controller,
                obscureText: true,
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  labelText: 'Enter your Number',
                ),
              ),
              actions: <Widget>[
                FlatButton(
                  child: Text('Submit'),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                )
              ],
            ));
      }
    
      /*
    
       */
    
    
      @override
      Widget build(BuildContext context) {
        if(_error) {
          return Text('error-game', textDirection: TextDirection.ltr);
        }
    
        // Show a loader until FlutterFire is initialized
        if (!_initialized) {
          return Text('Loading', textDirection: TextDirection.ltr);
        }
        return StreamBuilder<DocumentSnapshot>(
          stream: userSnapshot,
          builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
            if (snapshot.hasError) {
              return Text('Something went wrong');
            }
    
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Text("Loading");
            }
            if(snapshot.hasData){
              Map<String, dynamic> userDocument  = snapshot.data.data();
              print(collectionPath);
              print(docPath);
              print(snapshot.data);
              print(userDocument);
              gameResult = userDocument['status'];

//This one works fine

              if(gameResult =="win" || gameResult =="lose"){
                return _showMaterialDialog(gameResult);
              }

//This one causing errors


              if(gameResult=="on"){
                return _showMaterialDialogNumber();
              }
              kullanicisayilari = userDocument['atilansayi'];
              List<dynamic> kullanicisayilariDuz = [];
              List<dynamic> rakipsayilariDuz = [];
              List<dynamic> sonuclarDuz = [];
              for (var numbers in kullanicisayilari){
                var splittedNumber = numbers.split('|');
                kullanicisayilariDuz.add(splittedNumber[0]);
              }
              rakipsayilari = userDocument['rakipsallama'];
              sonuc = userDocument['sonuc'];
              for (var sonuclar in sonuc){
                var splittedSonuc = sonuclar.split('|');
                sonuclarDuz.add(splittedSonuc[0]);
              }
              for (var rakipsayi in rakipsayilari){
                var splittedRakipSayi = rakipsayi.split('|');
                rakipsayilariDuz.add(splittedRakipSayi[0]);
              }
              print(myNumbers.decimals);
              return MaterialApp(
                home:Scaffold(
                  appBar: AppBar(
                    backgroundColor: Colors.amberAccent,
                    title: Text('Sayı Avı Oyun Ekranı'),
                  ),
                  body:Column(
                    children: <Widget>[
                      Expanded(
                        flex: 80,
                        child: Row(
                          children: <Widget>[
                            Expanded(
                              flex: 40,
                              child: Column(
                                children: <Widget>[
                                  for(var numbers in kullanicisayilariDuz)Text(numbers),
                                  ]
                              ),
                            ),
                            Expanded(
                              flex: 10,
                              child: Column(
                                  children: <Widget>[
                                    for(var numbers in sonuclarDuz)Text(numbers),
                                  ]
                              ),
                            ),
                            Expanded(
                              flex: 50,
                              child: Column(
                                children: <Widget>[
                                  for(var numbers in rakipsayilariDuz)Text(numbers),
                                ]
                              ),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        flex:10,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            showDeleteNumbers(1,'numberimage1'),
                            showDeleteNumbers(2,'numberimage2'),
                            showDeleteNumbers(3,'numberimage3'),
                            showDeleteNumbers(4,'numberimage4'),
                            Expanded(
                              child:FlatButton(
                                onPressed: (){
                                  sendnumber();
                                },
                                child: Image.asset('images/send.png'),
                              ),
                            ),
                          ],
                        ),
                      ),
                      Expanded(
                        flex: 10,
                        child: Row(
                          children: <Widget>[
                            attachNumber('1','one.png'),
                            attachNumber('2','two.png'),
                            attachNumber('3','three.png'),
                            attachNumber('4','four.png'),
                            attachNumber('5','five.png'),
                            attachNumber('6','six.png'),
                            attachNumber('7','seven.png'),
                            attachNumber('8','eight.png'),
                            attachNumber('9','nine.png'),
                            attachNumber('0','zero.png'),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              );
            }
          },
        );
      }
    }

谢谢。

1 个答案:

答案 0 :(得分:1)

您的build的{​​{1}}函数需要返回一个GameScreen

Widget

但是,当您显示对话框时,您可以这样做:

Widget build(...) {}

此对话框函数返回一个return _showMaterialDialog(); ,它不能是窗口小部件。这说明了错误。

我希望显式声明它们,并且它们应该在异步函数内部返回对话框,如下所示:

Future<>

顺便说一句,使用相同的上下文传递给函数的参数应该更好:

Future _showMaterialDialog() async {
    ...
    return showDialog(...);
}

最后,为了正确使用这些对话框,只需显示它们并最后返回一个小部件:

Future _showMaterialDialog(BuildContext context) {
    // use the local 'context' to build the dialog
}

而且,如果您要显示UI的时间,则不需要添加两个if (...) { _showMaterialDialog(context); } return MaterialApp(...);
确实,由于使用delayed,因此尚未显示UI,您需要等待使用StreamBuilder刷新主渲染管道后:

addPostFrameCallback

PS:请记住,Flutter都是小部件,请考虑将您的代码重新编译为小部件,以避免只在一个类中做很多事情。