0

I am learning about provider package in which I created an app in which whatever I type in the TextField will change the title in the appbar and a text Widget below TextField. but it was not working so I started trying different codes and after some tries it started working when I changed the listen to false in the TextField onchanged.

I still don't understand why it started working after setting listen: false.

TextField(
  onChanged: (newValue) {
    Provider.of<Data>(context, listen: false).changeString(newValue);
  },
);
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider<Data>(create: (context) => Data()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(
          child: MyText(),
        ),
      ),
      body: Level1(),
    );
  }
}

class Level1 extends StatelessWidget {
  const Level1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Level2(),
    );
  }
}

class Level2 extends StatelessWidget {
  const Level2({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        MyTextField(),
        Level3(),
      ],
    );
  }
}

class Level3 extends StatelessWidget {
  const Level3({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(Provider.of<Data>(context).data);
  }
}

class MyText extends StatelessWidget {
  const MyText({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(Provider.of<Data>(context).data);
  }
}

class MyTextField extends StatelessWidget {
  const MyTextField({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: (newValue) {
        Provider.of<Data>(context, listen: false).changeString(newValue);
      },
    );
  }
}

class Data extends ChangeNotifier {
  String data = 'My Data';

  void changeString(String newString) {
    data = newString;
    notifyListeners();
  }
}
  • Does [Understand how listen: false works when used with Provider.of(context, listen: false)](https://stackoverflow.com/q/58584334/10157127) answer your question? – Md. Yeasin Sheikh Dec 12 '22 at 08:04

1 Answers1

0

Hello Harshdeep Singh,

In simple way if you set listen: false this means when ever notifyListeners() call this will not listen for the changes.

for example if the text update changeString(newValue) and listen: false it will not update the value.

final value = Provider.of<Data>(context, listen: false);
value.data; <-- data will not update when notifyListeners() call

when you set listen to true it will listen for the changes and update that value.

final value = Provider.of<Data>(context, listen: true);
value.data; <-- data will update when notifyListeners() call
Harsimran Singh
  • 269
  • 1
  • 7
  • yeah but in my case setting it to false is working. it should have worked with setting it to true. but when I set it true it doesn't work. I don't understand why it's reversed. – Harshdeep Singh Dec 14 '22 at 05:42
  • @HarshdeepSingh This exception happens because you're trying to listen to a provider from a life cycle that will never ever be called again. It means that you either should use another life-cycle (build), or explicitly specify that you do not care about updates. For example. In initState when you call Provider in initstate that will never ever be called again. same with onTap or onPress. – Harsimran Singh Dec 14 '22 at 11:03