Search code examples
androidfluttersetstateriverpodstate-management

I cannot display a changing value on the screen in my flutter application


I uploaded 3 pages of related code here. My problem is this: I press the Pick Country button and select a country, but I can't display my screen the phoneCode parameter of the country I selected.

I'm working with flutter_riverpod package and my class type is ConsumerWidget. So,I can't use the setState() command for this class.

I added a debugPrint to my void pickCountry() function. In this way, when I press the Pick Country button, I can see that the relevant value changes in the Debug Console section. My problem is that this value does not change on the screen.

Here is my problem on screen

all_providers.dart

final phoneControllerProvider =
    StateProvider<TextEditingController>((ref) => TextEditingController());

final countryProvider = StateProvider<Country?>((ref) => null);

country_code_and_text_field.dart //My Text Widget is here.


class CountryCodeAndTextField extends ConsumerWidget {
  const CountryCodeAndTextField({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final phoneController = ref.watch(phoneControllerProvider.notifier);
    final Country? country = ref.watch(countryProvider.notifier).state;

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        if (country != null)
          Text(
              '+${country.phoneCode}', // The part that needs to be updated according to the country I have selected.
            style: const TextStyle(color: Colors.white),
          )
        else
          const Text(
            '00',
            style: TextStyle(color: Colors.white),
          ),
        SizedBox(
          width: ScreenSize.getWidth(context) * 0.6,
          child: TextField(
            controller: phoneController.state,
            decoration: const InputDecoration(
              hintText: 'Enter your phone number',
              hintStyle: TextStyle(color: Colors.grey),
            ),
          ),
        ),
      ],
    );
  }
}

login_page.dart // My Pick Country button is here.

class LoginPage extends ConsumerWidget {
  const LoginPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    Country? currentCountry = ref.read(countryProvider.notifier).state;

    void pickCountry() {
      showCountryPicker(
        context: context,
        onSelect: (Country selectedCountry) {
          currentCountry = selectedCountry;
        },
      );
      debugPrint('selected phone code: ${currentCountry?.phoneCode}');
    }

    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text(
          'Enter your phone number',
          style: TextStyle(
            color: Colors.white,
          ),
        ),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          const Text(
            'Chattor will need to verify your phone number',
            style: TextStyle(color: Colors.grey),
          ),
          TextButton(
            onPressed: pickCountry,
            child: const Text(
              'Pick Country',
              style: TextStyle(color: Colors.amber),
            ),
          ),
          const CountryCodeAndTextField(),
          SizedBox(height: ScreenSize.getHeight(context) * 0.63),
          SizedBox(
            width: ScreenSize.getWidth(context) * 0.30,
            height: ScreenSize.getHeight(context) * 0.07,
            child: const NextButtonWidget(),
          ),
        ],
      ),
    );
  }
}

Solution

  • I think I need to use StateNotifierProvider instead of StateProvider to trigger the build method and change the screen in the flutter_riverpod package.

    class CountryNotifier extends StateNotifier<Country?> {
      CountryNotifier() : super(null);
    
      void setCountry(Country newCountry) {
        state = newCountry;
      }
    }
    
    final countryProvider = StateNotifierProvider<CountryNotifier, Country?>((ref) {
      return CountryNotifier();
    });
    
    void pickCountry() {
          showCountryPicker(
            context: context,
            onSelect: (Country selectedCountry) {
              ref.read(countryProvider.notifier).setCountry(selectedCountry);
            },
          );
        }
    

    After making these adjustments, my problem was solved.