How to change images using the Provider Package in Flutter

1.1k views Asked by At

Problem: I click the button 'do something' and the image can't seem to change from 'hello' to 'goodbye'. The error coming back is

'Error: The argument type 'Image' can't be assigned to the parameter type 'String'.

  • 'Image' is from 'package:flutter/src/widgets/image.dart' ('../../Development/flutter/packages/flutter/lib/src/widgets/image.dart'). return Image.asset(myValue);'

Is it possible to change the String into an image so it will read the image and display it on the screen?

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Provider<MyModel>(//                              <--- Provider
      create: (context) => MyModel(),
      child: Consumer<MyModel>( //                           <--- MyModel Consumer
          builder: (context, myModel, child) {
            return ValueListenableProvider<Image>.value( // <--- ValueListenableProvider
              value: myModel.someValue,
              child: MaterialApp(
                home: Scaffold(
                  appBar: AppBar(title: Text('My App')),
                  body: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[

                      Flexible(
                        child: Container(
                            padding: const EdgeInsets.all(20),
                            color: Colors.green[200],
                            child: Consumer<MyModel>( //       <--- Consumer
                              builder: (context, myModel, child) {
                                return RaisedButton(
                                  child: Text('Do something'),
                                  onPressed: (){
                                    myModel.doSomething();
                                  },
                                );
                              },
                            )
                        ),
                      ),

                      Flexible(
                        child: Container(
                          padding: const EdgeInsets.all(35),
                          color: Colors.blue[200],
                          child: Consumer<Image>(//           <--- String Consumer
                            builder: (context, myValue, child) {
                              return Image.asset(myValue);
                            },
                          ),
                        ),
                      ),

                    ],
                  ),
                ),
              ),
            );
          }),
    );
  }
}

class MyModel { //                                             <--- MyModel
  ValueNotifier<Image> someValue = ValueNotifier(Image.asset('images/hello.png')); // <--- ValueNotifier
  void doSomething() {
    someValue.value = Image.asset('images/goodbye.png');
    print(someValue.value);
  }
}
1

There are 1 answers

0
Maqcel On BEST ANSWER
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Provider<MyModel>(
      //                              <--- Provider
      create: (context) => MyModel(),
      child:
          Consumer<MyModel>(//                           <--- MyModel Consumer
              builder: (context, myModel, child) {
        return ValueListenableProvider<Image>.value(
          // <--- ValueListenableProvider
          value: myModel.someValue,
          child: MaterialApp(
            home: Scaffold(
              appBar: AppBar(title: Text('My App')),
              body: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Flexible(
                    child: Container(
                        padding: const EdgeInsets.all(20),
                        color: Colors.green[200],
                        child: Consumer<MyModel>(
                          //       <--- Consumer
                          builder: (context, myModel, child) {
                            return RaisedButton(
                              child: Text('Do something'),
                              onPressed: () {
                                myModel.doSomething();
                              },
                            );
                          },
                        )),
                  ),
                  Flexible(
                    child: Container(
                      padding: const EdgeInsets.all(35),
                      color: Colors.blue[200],
                      child: Consumer<Image>(
                        //           <--- String Consumer
                        builder: (context, myValue, child) {
                          return myValue; //                         <--- **Change** 
                        },
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }),
    );
  }
}

class MyModel {
  //                                             <--- MyModel
  ValueNotifier<Image> someValue =
      ValueNotifier(Image.asset('images/hello.png')); // <--- ValueNotifier
  void doSomething() { //                         <--- **Change** 
    if (someValue.value.toString() ==
        Image.asset('images/hello.png').toString()) {
      someValue.value = Image.asset('images/goodbye.png');
    } else if (someValue.value.toString() ==
        Image.asset('images/goodbye.png').toString()) {
      someValue.value = Image.asset('images/hello.png');
    }
  }
}

myValue is already an image so you don't need to open it again from Image.asset also added feature to change image back and forth for your doSomething() function