The argument type 'Widget Function(BuildContext)' cant be assigned to the parameter type 'Widget Function(BuildContext, Widget)' Error in Flutter

Viewed 27841

This is a code:

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

The line "builder: (_) => UserRepository.instance()," in above code shows a error

The argument type 'Widget Function(BuildContext)' cant be assigned to the parameter type 'Widget Function(BuildContext, Widget)'

and whenever I run the program it shows that

Could not find the correct Providerabove this LoginPage Widget

UserRepository code:

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

Please help

Here is a login page code:

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");
                }
              },
            )
          ],
        ),
      ),
    );
  }
}
8 Answers

In your code, simply change

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

to

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

and everything will work just fine!

I am very new to flutter and I had same issue, then I solved with this solution..

I replaced builder with create as shown in image.

enter image description here

for provider 3.2 and up you should use create instead of builder

from the version 5.0.0 of provider package, we should use 'create' instead of 'builder' in ChangeNotifierProvider .

Use create: instead builder: in ChangeNotifiereProvider()

Try with this:

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

I'm a little late but I would like to specify that we can use both create, build and they work too! Maybe I'm missing something but if docs still says that builder can be used I think we should.

By the way this is how you should use it to fix the error :

ChangeNotifierProvider(
      create: (_) => UserRepository.instance(),
      builder : (newContext,child){ //You will use this context here
          return Consumer....
      }
      child : CircularProgressIndicator(),

Be careful when using contexts, is easy to pass the wrong one. In this case you need to use newContext below. I used CircularProgressIndicator as child but you can use whatever you prefer.

you can put "BuildContext context, Widget? child" inside the round brackets(Parameter) of builder

Related