Search code examples
flutterprovider

Flutter Provider value is null


I'm trying to pass an index from a widget to another through a provider but the value returns by the provider context seems empty.

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create:(ctx)=> ProvideIDX(),
    child: Scaffold(
        body: Container(
      child: Stack(
        children: <Widget>[
          Maposm(lieu), //, idcarousel), // Pass index to this class
          Align(
            alignment: Alignment.bottomCenter,
            child: CarouselSlider.builder(
                itemCount: lieu.length,
                itemBuilder: (BuildContext ctx, index) {
                  return Container(
                      color: Colors.yellow, child:Text(lieu[index].name));
                },
                options: CarouselOptions(
                  enableInfiniteScroll: true,
                  scrollDirection: Axis.horizontal,
                  onPageChanged: (index, reason) {
                    setState(() {
                      Index(id: index);
                      print(index);
                    });
                  },
                )),
          ),
        ],
      ),
    )));
  }
}

class Places {
  String name;
  LatLng coordxy;

  Places({this.name, this.coordxy});
}

class Index {
  int id;
  Index({this.id});
}

class ProvideIDX with ChangeNotifier{
  Index _selectedID;
  set selectedID(id){
    this._selectedID = id;
    notifyListeners();
  }
  get selectedID=>this._selectedID;

}

And the provider is called inside Maposm class like this :

 @override
  Widget build(BuildContext context) {
    final _passIDX= Provider.of<ProvideIDX>(context);
    final  id = _passIDX.selectedID;
    print(id); // show null

and the result I got is "null", which of course is not the value I'd like to use ^^

edit: Even if the code is reduced it appears to be too long for the post. I uploaded the two classes and the yaml on Gdrive


Solution

  • Instead of:

    final _passIDX= Provider.of<ProvideIDX>(context);
    

    you should watch your provider:

    final _passIDX = context.watch<ProvideIDX>();
    

    Here is a Minimal Working Example:

    enter image description here

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    
    void main() {
      runApp(
        ChangeNotifierProvider(
          create: (ctx) => ProvideIDX(),
          child: MaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'Flutter Demo',
            home: HomePage(),
          ),
        ),
      );
    }
    
    class HomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: _Child(),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () =>
                Provider.of<ProvideIDX>(context, listen: false).increment(),
            child: Icon(Icons.add),
          ),
        );
      }
    }
    
    class _Child extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        final _passIDX = context.watch<ProvideIDX>();
        return Text(
          _passIDX.selectedID.toString(),
          style: TextStyle(fontSize: 96.0),
        );
      }
    }
    
    class Places {
      String name;
      Offset coordxy;
    
      Places({this.name, this.coordxy});
    }
    
    class Index {
      int id;
      Index({this.id});
    
      increment() => id++;
    
      toString() => id.toString();
    }
    
    class ProvideIDX with ChangeNotifier {
      Index _selectedID = Index(id: 0);
      get selectedID => _selectedID;
      set selectedID(id) {
        _selectedID = id;
        notifyListeners();
      }
    
      void increment() {
        _selectedID.increment();
        notifyListeners();
      }
    }