Flutter中的参数类型'Widget Function(BuildContext)'不能分配给参数类型'Widget Function(BuildContext,Widget)'错误

Posted

技术标签:

【中文标题】Flutter中的参数类型\'Widget Function(BuildContext)\'不能分配给参数类型\'Widget Function(BuildContext,Widget)\'错误【英文标题】:The argument type 'Widget Function(BuildContext)' cant be assigned to the parameter type 'Widget Function(BuildContext, Widget)' Error in FlutterFlutter中的参数类型'Widget Function(BuildContext)'不能分配给参数类型'Widget Function(BuildContext,Widget)'错误 【发布时间】:2020-08-30 22:25:54 【问题描述】:

这是一个代码:

import 'package:flutter/material.dart';
import 'package:flutterapp/ui/pages/notes_home.dart';
import 'package:provider/provider.dart';
import 'package:flutterapp/ui/pages/splash.dart';
import 'package:flutterapp/ui/pages/user_info.dart';
import 'package:flutterapp/ui/pages/auth/login.dart';
import 'package:flutterapp/model/user_repository.dart';
import 'package:path/path.dart';

class HomePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider(
      builder: (_) => UserRepository.instance(),
      child: Consumer
        // ignore: missing_return
        (builder: (context, UserRepository user, _) 
          // ignore: missing_return
          switch (user.status)
            case Status.Uninitialized:
              return Splash();
            case Status.Unauthenticated:
            case Status.Authenticating:
              return LoginPage();
            case Status.Authenticated:
              return NotesHomePage();
          
      ),
    );
  

上面代码中的“builder: (_) => UserRepository.instance()”行显示错误

参数类型'Widget Function(BuildContext)'不能赋值给参数类型'Widget Function(BuildContext, Widget)'

每当我运行程序时,它都会显示

在此 LoginPage 小部件上方找不到正确的提供程序

用户存储库代码:

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

enum Status  Uninitialized, Authenticated, Authenticating, Unauthenticated 

class UserRepository with ChangeNotifier 
  FirebaseAuth _auth;
  FirebaseUser _user;
  GoogleSignIn _googleSignIn;
  Status _status = Status.Uninitialized;

  UserRepository.instance()
      : _auth = FirebaseAuth.instance,
        _googleSignIn = GoogleSignIn() 
      _auth.onAuthStateChanged.listen(_onAuthStateChanged);
  

  Status get status => _status;
  FirebaseUser get user => _user;

  Future<bool> signIn(String email, String password) async
    try 
      _status = Status.Authenticating;
      notifyListeners();
      await _auth.signInWithEmailAndPassword(email: email, password: password);
      return true;
    catch(e)
      _status = Status.Unauthenticated;
      notifyListeners();
      return false;
    
  

  Future<bool> signUp(String email, String password) async
    try 
      _status = Status.Authenticating;
      notifyListeners();
      await _auth.createUserWithEmailAndPassword(email: email, password: password);
      return true;
    catch(e)
      _status = Status.Unauthenticated;
      notifyListeners();
      return false;
    
  

  Future<bool> signInWithGoogle() async
    try
      _status =Status.Authenticating;
      notifyListeners();
      final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
      final GoogleSignInAuthentication googleAuth =
          await googleUser.authentication;
      final AuthCredential credential = GoogleAuthProvider.getCredential(idToken: googleAuth.idToken, accessToken: googleAuth.accessToken);
      await _auth.signInWithCredential(credential);
      return true;
    catch(e) 
      print(e);
      _status = Status.Unauthenticated;
      notifyListeners();
      return false;
    
  

  Future signOut() async 
    _auth.signOut();
    _googleSignIn.signOut();
    _status = Status.Unauthenticated;
    notifyListeners();
    return Future.delayed(Duration.zero);
  

  Future<void> _onAuthStateChanged(FirebaseUser firebaseUser) async
    if(firebaseUser == null) 
      _status = Status.Unauthenticated;
    else
      _user = firebaseUser;
      _status = Status.Authenticated;
    
    notifyListeners();
  

请帮忙

enter image description here

这是一个登录页面代码:

import 'package:flutter/material.dart';
import 'package:flutterapp/model/user_repository.dart';
import 'package:provider/provider.dart';

class LoginPage extends StatefulWidget 
  @override
  _LoginPageState createState() => _LoginPageState();


class _LoginPageState extends State<LoginPage> 
  final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
  bool signInForm;
  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    signInForm = true;
  

  @override
  Widget build(BuildContext context) 
    final user = Provider.of<UserRepository>(context);
    return WillPopScope(
      onWillPop: () async
        if(!signInForm) 
          setState(() 
            signInForm = true;
          );
          return false;
        else
          return true;
        
      ,
      child: Scaffold(
        key: _key,
        backgroundColor: Colors.red,
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16.0),
          child: SizedBox(
            width: double.infinity,
            child: Column(
              children: <Widget>[
                const SizedBox(height: kToolbarHeight),
                Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    shape: BoxShape.circle,
                  ),
                  width: 60.0,
                  height: 60.0,
                ),
                const SizedBox(height: 30.0),
                RaisedButton(
                  textColor: Colors.red,
                  color: Colors.white,
                  child: Text('Google'),
                  onPressed: () async
                    if(!await user.signInWithGoogle())
                      showmessage();
                  ,
                ),
                const SizedBox(height: 30.0),
                AnimatedSwitcher(
                  child: signInForm ? LoginForm() : SignupForm(),
                  duration: Duration(milliseconds: 200),
                ),
                const SizedBox(height: 20.0,),
                OutlineButton(
                  textColor: Colors.white,
                  child: signInForm ? Text("Sign Up", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),) : Icon(Icons.arrow_back),
                  onPressed: () 
                    setState(() 
                      signInForm = !signInForm;
                    );
                  ,
                  color: Colors.white,
                  borderSide: BorderSide(color: Colors.white),
                  highlightColor: Colors.white,
                )
              ],
            ),
          )
        ),
      ),
    );
  
  void showmessage()
    _key.currentState.showSnackBar(SnackBar(
      content: Text("Somethimg is wrong"),
    ));
  


class LoginForm extends StatefulWidget 
  final Function showError;

  const LoginForm(Key key, this.showError) : super(key: key);
  @override
  _LoginFormState createState() => _LoginFormState();


class _LoginFormState extends State<LoginForm> 
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final FocusNode passwordField = FocusNode();
  TextEditingController _email;
  TextEditingController _password;

  @override
  void initState() 
    _email = TextEditingController();
    _password = TextEditingController();
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    final user = Provider.of<UserRepository>(context);
    return Container(
      padding: const EdgeInsets.all(16.0),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10.0),
      ),
      child: Form(
        key: _formKey,
        child: Column(
          children: <Widget>[
            Text("Login", style: Theme.of(context).textTheme.display1,),
            const SizedBox(height: 20.0),
            TextFormField(
              controller: _email,
              textInputAction: TextInputAction.next,
              decoration: InputDecoration(
                  labelText: "Email"
              ),
              onEditingComplete: ()
                FocusScope.of(context).requestFocus(passwordField);
              ,
            ),
            const SizedBox(height: 16.0,),
            TextFormField(
              controller: _password,
              focusNode: passwordField,
              obscureText: true,
              decoration: InputDecoration(
                  labelText: "Password"
              ),
            ),
            const SizedBox(height: 20.0),
            RaisedButton(
              textColor: Colors.red,
              child: Text("Login"),
              onPressed: () async
                if(_formKey.currentState.validate())
                  if(!await user.signIn(
                    _email.text, _password.text))
                    widget.showError();
                
              ,
            )
          ],
        ),
      ),
    );
  


class SignupForm extends StatefulWidget 
  @override
  _SignupFormState createState() => _SignupFormState();


class _SignupFormState extends State<SignupForm> 
  final FocusNode passwordField = FocusNode();
  final FocusNode confirmPasswordField = FocusNode();
  TextEditingController _email;
  TextEditingController _password;
  TextEditingController _confirmpassword;
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  void initState() 
    _email = TextEditingController();
    _password = TextEditingController();
    _confirmpassword = TextEditingController();
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    final user = Provider.of<UserRepository>(context);
    return Container(
      padding: const EdgeInsets.all(16.0),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(10.0),
      ),
      child: Form(
        key: _formKey,
        child: Column(
          children: <Widget>[
            Text("Sign Up", style: Theme.of(context).textTheme.display1,),
            const SizedBox(height: 20.0),
            TextFormField(
              controller: _email,
              textInputAction: TextInputAction.next,
              decoration: InputDecoration(
                  labelText: "Email"
              ),
              onEditingComplete: ()
                FocusScope.of(context).requestFocus(passwordField);
              ,
            ),
            const SizedBox(height: 16.0,),
            TextFormField(
              obscureText: true,
              controller: _password,
              focusNode: passwordField,
              decoration: InputDecoration(
                  labelText: "Password"
              ),
              onEditingComplete: ()=> FocusScope.of(context).requestFocus(confirmPasswordField),
            ),
            const SizedBox(height: 16.0,),
            TextFormField(
              obscureText: true,
              controller: _confirmpassword,
              focusNode: confirmPasswordField,
              decoration: InputDecoration(
                  labelText: "Confirm Password"
              ),
              onEditingComplete: ()
                FocusScope.of(context).requestFocus(passwordField);
              ,
            ),
            const SizedBox(height: 20.0),
            RaisedButton(
              textColor: Colors.red,
              child: Text("Create Account"),
              onPressed: () async
                if(_formKey.currentState.validate())
                  if(_confirmpassword.text == _password.text)
                    if(!await user.signUp(
                      _email.text, _password.text))
                      print("Failed to Signup");
                
              ,
            )
          ],
        ),
      ),
    );
  

【问题讨论】:

【参考方案1】:

在您的代码中,只需更改

builder: (_) => UserRepository.instance(),

create: (_) => UserRepository.instance(),

一切都会好起来的!

【讨论】:

谢谢。这让我很开心。花了一天时间找出错误消息,但我自己无法解决。再次感谢。【参考方案2】:

对于 provider 3.2 及更高版本,您应该使用 create 而不是 builder

【讨论】:

【参考方案3】:

我是 Flutter 的新手,遇到了同样的问题,然后我用这个解决方案解决了..

我将builder 替换为create,如图所示。

【讨论】:

【参考方案4】:

从 5.0.0 版本的提供程序包开始,我们应该在 ChangeNotifierProvider 中使用 'create' 而不是 'builder' 。 p>

【讨论】:

【参考方案5】:

使用 create: 代替 builder: in ChangeNotifiereProvider()

【讨论】:

【参考方案6】:

试试这个:

class HomePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider<UserRepository>(
      create: (context) => UserRepository.instance(),
      child: Consumer
        // ignore: missing_return
        (builder: (context, UserRepository user, child) 
          // ignore: missing_return
          switch (user.status)
            case Status.Uninitialized:
              return Splash();
            case Status.Unauthenticated:
            case Status.Authenticating:
              return LoginPage();
            case Status.Authenticated:
              return NotesHomePage();
          
      ),
    );
  

【讨论】:

android studio 中的错误消失了,使用上面的代码也完成了安装,但在 Mobile 中它无法正常工作。在屏幕上启动后显示错误:在此 LoginPage 小部件上方找不到正确的 Provider 你的日志是什么? 对不起,我没有明白你的问题....你说的日志是什么意思? 你为什么使用 *** WillPopScope*** ?

以上是关于Flutter中的参数类型'Widget Function(BuildContext)'不能分配给参数类型'Widget Function(BuildContext,Widget)'错误的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 参数类型 'List<dynamic>' 不能分配给参数类型 'List<Widget>'

Flutter 错误:无法将参数类型“List<Future<Widget>>”分配给参数类型“List<Widget>”

如何有条件地将参数传递给 Flutter/Dart 中的 Widget?

将 Future 类型化结果从函数分配给 Flutter Widget 中的变量

参数类型“Widget Function(Categoria)”不能分配给参数类型“dynamic Function(Child)”。 (型号)颤振

Flutter/Firestore - 类型 'List<dynamic>' 不是类型 'Widget' 的子类型