Why isn't the image changing using the Provider Package?

166

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;
Share:
166
Ned Bayne-Powell
Author by

Ned Bayne-Powell

Updated on December 01, 2022

Comments

  • Ned Bayne-Powell
    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
    Ned Bayne-Powell over 3 years
    Thanks 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
    Pieter van Loon over 3 years
    I cannot see the call to notifyListeners anywhere in the posted code. Can you update it to include it?
  • Ned Bayne-Powell
    Ned Bayne-Powell over 3 years
    Yes, I've added it in
  • Pieter van Loon
    Pieter van Loon over 3 years
    Ok 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
    Ned Bayne-Powell over 3 years
    Hi 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
    Pieter van Loon over 3 years
    In the Consumer you are also setting the image every build
  • Ned Bayne-Powell
    Ned Bayne-Powell over 3 years
    Would it be set image in the Consumer then?