Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call provider function in initstate #183

Closed
mhd-barikhan opened this issue Jul 31, 2019 · 14 comments
Closed

Call provider function in initstate #183

mhd-barikhan opened this issue Jul 31, 2019 · 14 comments

Comments

@mhd-barikhan
Copy link

mhd-barikhan commented Jul 31, 2019

there is an issue when try to call provider function inside initState() method

I'm using it as the following:

@OverRide

initState()
{
  super.initState();

  Provider.of<DataProvider>(context, listen: false).getData();

} 

the error log is:

I/flutter (15687):   * Ensure the Provider<DataProvider> is an ancestor to this MyHomePage Widget
I/flutter (15687):   * Provide types to Provider<DataProvider>
I/flutter (15687):   * Provide types to Consumer<DataProvider>
I/flutter (15687):   * Provide types to Provider.of<DataProvider>()
I/flutter (15687):   * Always use package imports. Ex: `import 'package:my_app/my_code.dart';
I/flutter (15687):   * Ensure the correct `context` is being used.
I/flutter (15687):
I/flutter (15687): If none of these solutions work, please file a bug at:
I/flutter (15687): https://github.com/rrousselGit/provider/issues

can you look into the issue, i've added listen: false but still show error.

Thanks

@rrousselGit
Copy link
Owner

Have you tried doing what the error suggests?
This is an error on your end. You likely forgot to add a provider, or inserted it in the wrong place.

@mhd-barikhan
Copy link
Author

this is my full code:

main.dart


import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_data_app/Provider/DataProvider.dart';
import 'package:provider_data_app/mainUI.dart';




void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
      
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );

    
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);


  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {


@override
initState()
{
  super.initState();
 Provider.of<DataProvider>(context, listen: false).getData();


} 



  @override
  Widget build(BuildContext context) {

    return  ChangeNotifierProvider(
          
          builder: (_) => DataProvider(),
          
          child: MainUI()
          );
            
      


    
  }










}

MainUI.dart



import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_data_app/Provider/DataProvider.dart';


class MainUI extends StatelessWidget {



  @override
  Widget build(BuildContext context) {



return Scaffold(
      appBar: AppBar(
      
        title: Text('provider app'),
      ),
      body: Center(

        child:  Consumer<DataProvider>(
  builder: (context, dataProvider, child) {

      return dataProvider.isBusy? Text('busy') :  Text(dataProvider.dbVersion);

  }
        )
    
       
      ),
      floatingActionButton: FloatingActionButton(
        //listen false to rebuild only inside Consumer not full widget
       onPressed:()=> Provider.of<DataProvider>(context,listen: false).getData(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      
  
      )

  
       
    );

  }
}

DataProvider.dart



import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';



class DataProvider with ChangeNotifier {
  String _dbVersion = '';
  String get dbVersion => _dbVersion;

  bool _isBusy=false;
  bool get isBusy => _isBusy;



  set isBusy(bool value)
  {
      _isBusy=value;
      notifyListeners();
  }

  Future<void> getData() async{
  


          isBusy=true;
      
          _dbVersion=await getDbVersion();

         

          isBusy=false;
        
        
          

    

}




  Future<String> getDbVersion() async {
   return '2.2.0';
   }






}



i don't know why Provider.of(context, listen: false).getData(); not working in initstate and give me an error

@adriancmurray
Copy link

@rrousselGit gave the answer, you're inserting it in the wrong place. Your initState is calling a function on a Provider that hasn't been built yet. You need to create the provider and then call that function later down the widget tree in a different initstate.

@renanserrou
Copy link

Try to setup your ChangeNotifierProvider before MaterialApp.

@karmazinkd
Copy link

For anyone who is reading this thread and still doesn't know what to do here is a great explanation: https://pub.dev/packages/provider#faq and the first question:

I have an exception when obtaining Providers inside initState. What can I do?

@Santiago1709
Copy link

I'd say it is because you are calling a setState() when notifying listeners, and you cant do that when widgets are building. You should this:

void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
Provider.of(context,listen:false).yourFunctionWithNotifyListener();
});
super.initState();
}

!!REMEMBER TO ADD LISTEN:FALSE

@sanba-anass
Copy link

context is not avaliable in initstate how we can call it in initstate anyway

@bhanuka96
Copy link

bhanuka96 commented May 19, 2022

@rrousselGit

It is safe to use provider in initState without using addPostFrameCallback if there are no rebuilding things like (notifyListeners or showing alert). right?

Example:

@override
void initState() {
super.initState();
var userNotifier = Provider.of<ValueNotifier<UserModel>>(context, listen: false); <-- already has value
controller.text = userNotifier.value.displayName;
 }

@sajibsaha4647
Copy link

@bhanuka96 getting error ...`import 'package:flutter/material.dart';
import 'package:fluttermvvm/Utils/Routes/Routes.dart';
import 'package:fluttermvvm/Utils/Routes/RoutesName.dart';
import 'package:fluttermvvm/View/LoginScreen.dart';
import 'package:fluttermvvm/ViewModel/AuthViewmodel/AuthViewModel.dart';
import 'package:fluttermvvm/ViewModel/AuthViewmodel/RegistrationViewModel.dart';
import 'package:provider/provider.dart';

import 'ViewModel/HomeViewModel/HomeViewModel.dart';
import 'ViewModel/UserViewModel/UserViewModel.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);

// This widget is the root of your application.
@OverRide
Widget build(BuildContext context) {
return MultiProvider(providers: [
ChangeNotifierProvider(create: ()=>AuthViewmodel()),
ChangeNotifierProvider(create: (
)=>RegistrationViewModel()),
ChangeNotifierProvider(create: ()=>UserViewModel()),
ChangeNotifierProvider(create: (
)=>HomeViewModel()),

],child: MaterialApp(
  debugShowCheckedModeBanner: false,
  initialRoute: RoutesName.splashscreen,
  onGenerateRoute: Routes.generateRoute ,
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: LoginScreen(),
));

}
}

`

@sajibsaha4647
Copy link

` @OverRide

void initState() {
super.initState();
var UserDatamodels = Provider.of(context) ;
UserDatamodels.fetchUserDataApi();
}`

@sajibsaha4647
Copy link

after using app going crash please help ??

@bhanuka96
Copy link

@sajibsaha4647 Use this way

var UserDatamodels = Provider.of(context, listen: false) ;
UserDatamodels.fetchUserDataApi(); // don't use any setState(notifyListeners) inside this model.

use this way If you want to use setState or notifyListerners after calling you function

WidgetsBinding.instance.addPostFrameCallback((_) {
var UserDatamodels = Provider.of(context, listen: false) ;
UserDatamodels.fetchUserDataApi();
});

@AdnanGriezmann
Copy link

how i use stateless widget with provider statemanagement

@AdnanGriezmann
Copy link

i call api but i want to not using statefullwidget or inistate method how can i achieve provider api call without initstate method.
help plz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants