2

I am creating a very simple app to practice flutter provider package. The app has a bulb which on click , should change it's background and the screen's background , using provider. But this doesnt seem to work. TBH this is a lot confusing

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

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

class Data extends ChangeNotifier{
  bool isOn = false;
  void toggle(){
    this.isOn = !this.isOn;
    notifyListeners();
    print("new value is $isOn");
  }
}

class MainApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Data>(
      create: (context) => Data(),
      child: MaterialApp(
        home: Home(),
      ),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      backgroundColor: Provider.of<Data>(context).isOn ? Colors.yellow[100] : Colors.black,
      body: Center(
        child: Column(
          children: <Widget>[
            Stick(),
            Bulb(),
          ],
        ),
      ),
    );
  }
}

class Stick extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 150,
      width: 40,
      color: Colors.brown,
    );
  }
}

class Bulb extends StatefulWidget {
  @override
  _BulbState createState() => _BulbState();
}

class _BulbState extends State<Bulb> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 200,
      width: 250,
      decoration: BoxDecoration(
          borderRadius: BorderRadius.only(
              topLeft: Radius.circular(100),
              topRight: Radius.circular(100),
              bottomLeft: Radius.circular(30),
              bottomRight: Radius.circular(30)),
          color: Provider.of<Data>(context).isOn ? Colors.yellow : Colors.white,
      ),
      child: GestureDetector(
        onTap: (){
          Provider.of<Data>(context).toggle();
          setState(() {
          });
        },
      ),
    );
  }
}

The tree structure has a main app which houses a Home app , which houses 2 other widgets , a stick and a bulb inside a container. I am trying to update the background of bulb and the Home widget when the bulb is clicked. Bulb has a gesture detector Any kind of hint or help appreciated

2 Answers 2

3

Try to add listen: false to the provider call :

Provider.of<Data>(context, listen: false).toggle();
Sign up to request clarification or add additional context in comments.

3 Comments

It worked ! Please explain how did that work ! Also do point out if there is anything wrong with the way I am using provider
I don't know exactly why, but this is the doc on it : If [listen] is true, later value changes will trigger a new [State.build] to widgets, and [State.didChangeDependencies] for [StatefulWidget].
For anyone still looking for other ways to use provider, try Consumer<T> widget. it is better than calling Provider.of( ) each time
0

The problem is because Provider constructor has a named parameter listen which is equal to true by default. And this behavour force rebuilding while you use Provider.of() method. It is imposible to call build while current buiding is still active. That is why you suggested to set listen to false because it disables default behavour.

It is better to implement like this:

...

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Consumer<Data>(
      builder: (_, data, __) {
        return Scaffold(
          appBar: AppBar(),
          backgroundColor: data.isOn ? Colors.yellow[100] : Colors.black,
          body: Center(
            child: Column(
              children: <Widget>[
                Stick(),
                Bulb(),
              ],
            ),
          ),
        );
      }
    );
  }
}
...

class _BulbState extends State<Bulb> {
  @override
  Widget build(BuildContext context) {
    return Consumer<Data>(
      builder: (_, data, __) {
        return Container(
          height: 200,
          width: 250,
          decoration: BoxDecoration(
            borderRadius: BorderRadius.only(
              topLeft: Radius.circular(100),
              topRight: Radius.circular(100),
              bottomLeft: Radius.circular(30),
              bottomRight: Radius.circular(30)
            ),
            color: data.isOn ? Colors.yellow : Colors.white,
          ),
          child: GestureDetector(
            onTap: () {
              data.toggle();
              setState(() {});
            },
          ),
        );
      },
    );
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.