SugiuraY
SugiuraY

Reputation: 351

How should I manage multiple Provider and Consumer

I'm coding textfield with river_pod library as follows. When I tapped each suffixIcon, it works both password and password-confirmation field and finally it figured out that each state is only managed by single provider. And wonder how should I manage this provider and consumer separately, and effectively.

//main.dart
import 'package:cards/view/textfield.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(
    ProviderScope(
      child: MaterialApp(
        title: 'Cards Demo',
        home: RegisterWidget(),
      ),
    ),
  );
}

class RegisterWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        body: Padding(
      padding: const EdgeInsetsDirectional.fromSTEB(20, 50, 20, 0),
      child: Column(
        children: [
          Container(
            width: double.infinity,
            height: 50,
            // color: Colors.grey,
            alignment: Alignment.topLeft,
            child: Image.asset('images/logo.png'),
          ),
          Container(
            padding: const EdgeInsetsDirectional.fromSTEB(10, 0, 10, 0),
            margin: const EdgeInsets.only(top: 30),
            width: double.infinity,
            // color: Colors.blue,
            child: Column(
              children: [
                const Align(
                  alignment: AlignmentDirectional(0, 0),
                  child: TextFieldCustom(
                    labelText: "email",
                    hintText: "type your email-adress",
                    suffixIcon: null,
                  ),
                ),
                Align(
                  alignment: const AlignmentDirectional(0, 0),
                  child: TextFieldCustom(
                      labelText: "password",
                      hintText: "set password",
                      suffixIcon: SuffixIconWidget()),
                ),
                Align(
                  alignment: const AlignmentDirectional(0, 0),
                  child: TextFieldCustom(
                      labelText: "password-confirm",
                      hintText: "password for confirmation",
                      suffixIcon: SuffixIconWidget()),
                ),
              ],
            ),
          ),
        ],
      ),
    ));
  }
}

//textfield.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

final mask = StateProvider<bool>((ref) => true);

class TextFieldCustom extends ConsumerWidget {
  const TextFieldCustom({required this.labelText, required this.hintText, this.suffixIcon, Key? key}): super(key: key);
  final String labelText;
  final String hintText;
  final Widget? suffixIcon;


  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Container(
        margin: const EdgeInsets.only(bottom: 10),
        child: TextFormField(
          style: const TextStyle(
            fontSize: 13,
          ),
          obscureText: ObscureTextFunction(suffixIcon, ref),
          decoration: InputDecoration(
            labelText: labelText, //**
            hintText: hintText, //**
            suffixIcon: suffixIcon, //**
            labelStyle: const TextStyle(
              fontSize: 15,
              color: Color.fromARGB(255, 219, 219, 219), 
            ),
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(2),
              borderSide: const BorderSide(
                color: Color.fromARGB(255, 219, 219, 219), 
                width: 1.0,
              ),
            ),
            focusedBorder: OutlineInputBorder(
                borderRadius: BorderRadius.circular(2),
                borderSide: const BorderSide(
                  color: Color.fromARGB(255, 219, 219, 219),
                  width: 1.0, //outlineの太さ
                )),
          ),
        ));
  }
}

bool ObscureTextFunction(suffixIcon, ref) {
  if (suffixIcon == null) {
    return false;
  } else {
    final bool isVisible = ref.watch(mask);
    return isVisible ? false : true;
  }
}

class SuffixIconWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final bool isVisible = ref.read(mask);
    return IconButton(
      icon: Icon(ref.watch(mask) // false
          ? FontAwesomeIcons.solidEye
          : FontAwesomeIcons.solidEyeSlash),
      onPressed: () {
        ref.read(mask.notifier).update((state) => !isVisible);
      },
    );
  }
}

Additional Code

final mask = StateProvider<bool>((ref) => true);
final maskConfirm = StateProvider<bool>((ref) => true);

class SuffixIconWidget extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final bool isVisible = ref.read(mask);

    return IconButton(
      icon: Icon(ref.watch(mask) // false
          ? FontAwesomeIcons.solidEye
          : FontAwesomeIcons.solidEyeSlash),
      onPressed: () {
        ref.read(mask.notifier).update((state) => !isVisible);
      },
    );
  }
}

class SuffixIconWidgetConfirm extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final bool isVisible = ref.read(maskConfirm);

    return IconButton(
      icon: Icon(ref.watch(maskConfirm) // false
          ? FontAwesomeIcons.solidEye
          : FontAwesomeIcons.solidEyeSlash),
      onPressed: () {
        ref.read(maskConfirm.notifier).update((state) => !isVisible);
      },
    );
  }
}

Upvotes: 0

Views: 353

Answers (1)

FLjubic
FLjubic

Reputation: 191

For local states that are only important for the widget, I would just recommend you have a simple boolean in TextFieldCustom and change it with setState.

Generally speaking though, for this widget to be correctly reusable with Riverpod, you should create a callback function onIconPressed(). Just like you are passing labelText, suffixIcon etc., in Flutter you can also pass functions like you do for buttons. Then for one provider to work on both widgets, it shouldn't be a provider of boolean, but instead of an object that holds two booleans.

Upvotes: 1

Related Questions