House MD
House MD

Reputation: 53

How to listen to multiple sources in flutter using a ChangeNotifier?

I have the widget whose text needs to update based on what is entered in two TextFields. What is the right way to listen to two sources in this situation (and in general)?

I just wrote two classes:

class MyTextField extends StatelessWidget {
  const MyTextField({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return TextField(
      onChanged: (newData) => context.read<Data>().changeString(newData),
    );
  }
}

And MyTextField2 the same.

The HomePage widget:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('build HomePage');
    return Scaffold(
      appBar: AppBar(
        title: Container(child: Text(context.watch<Data>().getData),),
      ),
      body: Center(
        child: Column(
          children: [
            MyTextField(),
            MyTextField2(),
            Text(context.watch<Data>().getData),
          ],
        ),
      )
    );
  }
}

The Data class:

class Data with ChangeNotifier
{
  String _data = 'some text';
  String get getData => _data;

  void changeString(String newString)
  {
    _data = newString;
    notifyListeners();
  }
}

Am I correct in that the HomePage widget is listening to two sources? Can conflicts occur if both TextField are changed at the same time?

Upvotes: 1

Views: 1932

Answers (2)

Ma Jeed
Ma Jeed

Reputation: 932

I tested your code and it worked fine. this is the main file:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'Data.dart';
import 'MyTextField.dart';
import 'MyTextField2.dart';

void main() {
runApp(
  ChangeNotifierProvider<Data>(
    create: (_) => Data(),
    child: MyApp(),
));
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
 title: 'Flutter Demo',
 theme: ThemeData(
  primarySwatch: Colors.blue,
 ),
home: HomePage(),
  );
 }
}

class HomePage extends StatelessWidget {
@override
return Scaffold(
    appBar: AppBar(
      title: Container(child: Text(context.watch<Data>().getData),),
    ),
    body: Center(
      child: Column(
        children: [
          MyTextField(),
          MyTextField2(),
          Text(context.watch<Data>().getData),
        ],
      ),
    )
);
 }
}

this is the result:

enter image description here

if you want to combine the two TextFields you can change your Data class to:

import 'package:flutter/material.dart';

class Data with ChangeNotifier{
String _data1 = "";
String _data2 = "";
String get getData => _data1+_data2;

void changeString1(String newString){
    _data1 =newString;
    notifyListeners();
 }
void changeString2(String newString){
   _data2 =newString;
   notifyListeners();
 }
}

this is the result:

enter image description here

Upvotes: 0

Muhammet
Muhammet

Reputation: 89

You can wrap MaterialApp in your main.dart file with MultiProvider(providers: [//your providers])

Upvotes: 1

Related Questions