Why isn't the image changing using the Provider Package?
You have to call notifyListeners
in your model when the image has changed otherwise the changenotifierprovider will not know that it needs to rebuild.
One way of doing the would be to wrap the image field with a getter and setter and call notifyListeners in the setter after updating the underlying field.
var Image _image;
set image(Image value) {
_image = value;
notifyListeners();
}
Image get image => _image;
Ned Bayne-Powell
Updated on December 01, 2022Comments
-
Ned Bayne-Powell over 1 year
I'm working with the Provider Package on Flutter but can't work out why it's not changing the background image when I call
mymodel.image
. It should access the MyModal class and change the existing image: Image.asset('images/background_image.jpeg', fit: BoxFit.fill) with the one in the SmallImage screen.mymodel.image = Image.asset('images/hello_image.png', fit: BoxFit.fill);
Which replaces the background image on the HomePage.
HomePage Screen
import 'package:flutter/material.dart'; import 'package:flutter_app_background/small_images.dart'; import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider<MyModel>( create: (context) => MyModel(), child: MaterialApp( title: 'Title', home: HomePage(), ), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( extendBodyBehindAppBar: true, appBar: AppBar( title: Text('Background Image', style: TextStyle( color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold), ), iconTheme: IconThemeData(color: Colors.white), actions: <Widget>[ IconButton( icon: Icon(Icons.settings, color: Colors.black,), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => SmallImages()), ); }, ), ], backgroundColor: Colors.transparent, elevation: 0.0, ), body: Stack( children: <Widget> [ Positioned.fill( child: GestureDetector( child: Consumer<MyModel>( builder: (context, myModel, child) { return myModel.image = Image.asset('images/background_image.jpeg', fit: BoxFit.fill); }, ), ), ), ], ), ); } } class MyModel extends ChangeNotifier { Image _image; set image(Image value) { _image = value; notifyListeners(); } Image get image => _image; }
SmallImage Screen
import 'package:flutter/material.dart'; import 'package:flutter_app_background/main.dart'; import 'package:provider/provider.dart'; class SmallImages extends StatefulWidget { static int tappedGestureDetector = 1; @override _SmallImagesState createState() => _SmallImagesState(); } class _SmallImagesState extends State<SmallImages> { List<bool> isSelected; void initState() { isSelected = [true, false, false, false, false, false, false, false, false]; super.initState(); } @override Widget build(BuildContext context) { final mymodel = Provider.of<MyModel>(context,listen:false); //default for listen is `true` return Scaffold( appBar: AppBar( title: Text('Small Image', style: TextStyle( color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold), ), iconTheme: IconThemeData(color: Colors.white), actions: <Widget>[ IconButton( icon: Icon(Icons.arrow_left, color: Colors.black,), onPressed: () { Navigator.pop( context, MaterialPageRoute(builder: (context) => HomePage()), ); }, ), ], backgroundColor: Colors.transparent, elevation: 0.0, ), body: Material( child: GestureDetector( child: MaterialApp( builder: (context, snapshot) { return GridView.count( crossAxisCount: 1, childAspectRatio: 1.0, padding: const EdgeInsets.all(4.0), mainAxisSpacing: 0.0, crossAxisSpacing: 0.0, children: [ GridView( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: MediaQuery .of(context) .size .width / (MediaQuery .of(context) .size .height / 2), ), children: [ GestureDetector( onTap: () { // return myValue; setState(() { SmallImages.tappedGestureDetector = 1; }); return mymodel.image = Image.asset('images/hello_image.png', fit: BoxFit.fill); print('hi'); }, child: Container( height: 100, width: 107, decoration: BoxDecoration(border: SmallImages .tappedGestureDetector == 1 ? Border.all( color: Color(0xff2244C7), width: 1.0) : Border .all(color: Colors.transparent,),), child: Image.asset( 'images/nightsky_image.png', ), ), ), Consumer<MyModel>( builder: (context, myModel, child) { return GestureDetector( onTap: () { setState(() { SmallImages.tappedGestureDetector = 2; }); // <-- replaced 'tapped' and 'other' }, child: Container( height: 100, width: 107, decoration: BoxDecoration(border: SmallImages .tappedGestureDetector == 2 ? Border.all( color: Color(0xff2244C7), width: 1.0) : Border .all(color: Colors.transparent,),), child: Image.asset( 'images/own_image.png', ), ), ); }, ), Consumer<MyModel>( builder: (context, myModel, child) { return GestureDetector( onTap: () { setState(() { SmallImages.tappedGestureDetector = 3; }); // <-- replaced 'tapped' and 'other' }, child: Container( height: 100, width: 107, decoration: BoxDecoration(border: SmallImages .tappedGestureDetector == 3 ? Border.all( color: Color(0xff2244C7), width: 1.0) : Border .all(color: Colors.transparent,),), child: Image.asset( 'images/iceland_image.png', ), ), ); }, ), ].toList(), ), ], ); }), ), ), ); } }
-
Ned Bayne-Powell over 3 yearsThanks for the answer, I've called it inside here but it's still not working: class MyModel extends ChangeNotifier { Image image = Image.asset('images/background_image.jpeg', fit: BoxFit.fill); notifyListeners(); }
-
Pieter van Loon over 3 yearsI cannot see the call to notifyListeners anywhere in the posted code. Can you update it to include it?
-
Ned Bayne-Powell over 3 yearsYes, I've added it in
-
Pieter van Loon over 3 yearsOk I think you don’t quite understand the code. You adden a method to your model that calls notifyListeners howeer that onChange method is still never called. When you set the new value to the image you need to call notifyListeners. One way of doing the would be to wrap the image field with a getter and setter and call notifyListeners in the setter after updating the underlying field.
-
Ned Bayne-Powell over 3 yearsHi Pieter, I've updated the code with your answer, would you be able to please have a look at it one last time as I'm still getting the image change?
-
Pieter van Loon over 3 yearsIn the Consumer you are also setting the image every build
-
Ned Bayne-Powell over 3 yearsWould it be set image in the Consumer then?