androidflutterdartprovider

Provider not updating value


I have a provider that sets a value for pin, but i cannot access its value from another screen, what i'm doing wrong? I have tried many ways to solve it but i cant make it work.

The widget where i set the pin value:

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

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => PinValue(),
      child: PinputExample(),
    );
  }
}

class PinputExample extends StatefulWidget {
  const PinputExample({Key? key}) : super(key: key);

  @override
  State<PinputExample> createState() => _PinputExampleState();
}

class _PinputExampleState extends State<PinputExample> {
  final pinController = TextEditingController();
  final focusNode = FocusNode();
  final formKey = GlobalKey<FormState>();

  @override
  void dispose() {
    pinController.dispose();
    focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<PinValue>(
        create: (_) => PinValue(),
        child: Consumer<MyTheme>(builder: (context, myTheme, child) {
          const focusedBorderColor = Color(0xFF9500c8);
          const fillColor = Color.fromRGBO(243, 246, 249, 0);
          var borderColor = myTheme.primaryColor;

          return Form(
            key: formKey,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Directionality(
                  textDirection: TextDirection.ltr,
                  child: Pinput(
                    controller: pinController,
                    focusNode: focusNode,
                    androidSmsAutofillMethod:
                        AndroidSmsAutofillMethod.smsUserConsentApi,
                    listenForMultipleSmsOnAndroid: true,
                    defaultPinTheme: defaultPinTheme,
                    validator: (value) {
                      return value == '222222' ? null : 'Pin is incorrect';
                    },
                    onCompleted: (pin) {
                      debugPrint('onCompleted: $pin');
                      Provider.of<PinValue>(context, listen: false).setPin(pin);
                      print(Provider.of<PinValue>(context, listen: false).pin);
                      //Where i set the value for pin. Here it prints normally
                    },
                    onChanged: (value) {
                      debugPrint('onChanged: $value');
                    },
                    cursor: Column(
                      mainAxisAlignment: MainAxisAlignment.end,
                      children: [
                        Container(
                          margin: const EdgeInsets.only(bottom: 9),
                          width: 22,
                          height: 1,
                          color: focusedBorderColor,
                        ),
                      ],
                    ),
                    errorPinTheme: defaultPinTheme.copyBorderWith(
                      border: Border.all(color: Colors.redAccent),
                    ),
                  ),
                ),
              ],
            ),
          );
        }));
  }
}

The widget where i try to access the value of pin (but gets a empty string):


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

  @override
  Widget build(BuildContext context) {
    return Consumer<PinValue>(builder: (context, pinValue, child) {
      return Scaffold(
        body: Container(
          child: Padding(
            padding: const EdgeInsets.all(24.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const SizedBox(
                  height: 40,
                ),
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const PinputExample(),
                    const SizedBox(height: 80),
                    ReusableButton(
                      text: "Validate",
                      onPressed: () {
                        print(pinValue.pin); 
                        //Where i try to print the value and get the empty string
                        Navigator.pushReplacement(
                          context,
                          MaterialPageRoute(
                            builder: (context) => TakePhotoScreen(),
                          ),
                        );
                      },
                    ),
                    const SizedBox(
                      height: 25,
                    ),
                    Text("Reenviar token", style: CustomTextStyle.h2()),
                    Text(pinValue.pin, style: CustomTextStyle.h2())
                  ],
                ),
              ],
            ),
          ),
        ),
      );
    });
  }
}

PinValue class

import 'package:flutter/material.dart';

class PinValue with ChangeNotifier {
  String _pin = '';

  String get pin => _pin;

  void setPin(String pin) {
    _pin = pin;
    notifyListeners();
  }
}


According to examples that i see i cannot find what is wrong, can someone help me?


Solution

  • You don't need to create provider on PinputExample.

    Replace

     @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider<PinValue>(
            create: (_) => PinValue(),
            child: Consumer<MyTheme>(builder: (context, myTheme, child) {
    

    With

     @override
      Widget build(BuildContext context) {
        return Consumer<MyTheme>(builder: (context, myTheme, child) {
    

    You may wrap the MaterialApp with Provider and then use all over the app, for this case, you also need to remove PinDemo's provider's create. Just use consumer widget.

    ChangeNotifierProvider<PinValue>(
            create: (_) => PinValue(),
            child: PinDemo()
    

    Or you can pass provider value using route.