1

I am new to flutter. I want to ask why when my text field's onChange did not trigger: "Provider.ofContext).updateData(newString);". The value of my Provider.of(context).data is not updated and with the 2 print statements, only 'called1' is always printed out.

Here is the code: import 'package:flutter/material.dart'; import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Data>(
      create: (_) => Data(),
      lazy: false,
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text(Provider.of<Data>(context).data),
          ),
          body: Level2(),
        ),
      ),
    );
  }
}


class Level2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        MyTextField(),
      ],
    );
  }
}

class MyTextField extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return TextField(onChanged: (newString) {
      print('called1');
      Provider.of<Data>(context).updateData(newString);
      print('called2');
    });
  }
}

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

  void updateData(newString) {
    data = newString;
    notifyListeners();
  }
}
robertos95
  • 63
  • 1
  • 8

1 Answers1

1

You are trying to access provider in same widget where you are declaring, which is not right way to do, provider must declare in above widget where you are accessing.

Moreover always use provider data by variable(as used in MyTextField widget) other wise it will not work.

Following code may help you to understand more.

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

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

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

class Level1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(Provider.of<Data>(context).data),
      ),
      body: Level2(),
    );
  }
}

class Level2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        MyTextField(),
      ],
    );
  }
}

class MyTextField extends StatelessWidget {
  var dataprovider;
  @override
  Widget build(BuildContext context) {
    dataprovider = Provider.of<Data>(context);
    return TextField(
      onChanged: (newString) {
        print(dataprovider.data);
        dataprovider.updateData(newString);
        print('called2');
      },
    );
  }
}

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

  void updateData(newString) {
    print("cds");
    data = newString;
    notifyListeners();
  }
}
Viren V Varasadiya
  • 25,492
  • 9
  • 45
  • 61
  • This works! Thank you!! So in every widget that needs data provider, I will need to always redeclare the data provider or at least pass it from the parent widget? – robertos95 Apr 13 '20 at 16:50
  • there is no need to pass data provider. you can access as i show in MyTextField widget but make sure it's parent widget has dataprovider. – Viren V Varasadiya Apr 13 '20 at 16:54