dart 在flutter应用程序中将全局变量转换为riverpod提供程序

b09cbbtk  于 2023-09-28  发布在  Flutter
关注(0)|答案(1)|浏览(124)

我很难在我的Flutter应用程序中使用Riverpod提供商。我以前使用过全局变量,但我想将它们转换为提供程序类。

由于字符限制,我删除了原始代码。

你能帮帮我吗?谢谢你

    • 我所改变的是正确的吗?下面是提供程序类:
class GlobalsProvider extends ChangeNotifier {
  GlobalsProvider._();

  // This is assigned in the Login screen
  static final currentUid = StateProvider<String?>((ref) => null);
  static final currentUEmail = StateProvider<String?>((ref) => null);

  // This is assigned in  agent_profile screen
  //String agentDocumentId;
  // ======  populated in login_screen.dart  =======
  String? companyId;
  String? mlsId;
  String? currentTrxnId;
  String? currentCompanyName;
  String? currentCompanyState;
  String? currentUserId;
  String? currentUserState;
  String? currentUserName;
  // ===============================================
  String? selectedState;
  String? selectedUserState;
  String? selectedTrxnState;
  String? selectedCompany;
  String? selectedUser;
  int? targetScreen;
  bool? newEvent;

  bool? newTrxn;
  bool? newUser;
  bool? newCompany;

  // changeCurrentUId(String value) {
  //   companyId = value;
  //   notifyListeners();
  // }

  void changeCurrentUId(WidgetRef ref, String newUID){
    ref.read(GlobalsProvider.currentUid.notifier).state = newUID;
    // or if you need previous state use update method
    //ref.read(MyGlobalProvider.currentUid.notifier).update((previousUID)=> newUID);
  }

  // changecurrentUEmail(String value) {
  //   currentUEmail = value;
  //   notifyListeners();
  // }  

  void changecurrentUEmail(WidgetRef ref, String newUEmail){
    ref.read(GlobalsProvider.currentUEmail.notifier).state = newUEmail;
    // or if you need previous state use update method
    //ref.read(MyGlobalProvider.currentUid.notifier).update((previousUID)=> newUID);
  }
  
  changeCompanyId(String value) {
    companyId = value;
    notifyListeners();
  }

  changeMlsId(String value) {
    mlsId = value;
    notifyListeners();
  }

  changeCurrentTrxnId(String value) {
    currentTrxnId = value;
    notifyListeners();
  }

  changeCurrentCompanyName(String value) {
    currentCompanyName = value;
    notifyListeners();
  }

  changeCurrentCompanyState(String value) {
    currentCompanyState = value;
    notifyListeners();
  }

  changeCurrentUserId(String value) {
    currentUserId = value;
    notifyListeners();
  }

  changeCurrentUserState(String value) {
    currentUserState = value;
    notifyListeners();
  }

  changeCurrentUserName(String value) {
    currentUserName = value;
    notifyListeners();
  }

  changeSelectedState(String value) {
    selectedState = value;
    notifyListeners();
  }

  changeSelectedUserState(String value) {
    selectedUserState = value;
    notifyListeners();
  }

  changeSelectedTrxnState(String value) {
    selectedTrxnState = value;
    notifyListeners();
  }

  changeSelecteCompany(String value) {
    selectedCompany = value;
    notifyListeners();
  }

  changeSelectedUser(String value) {
    selectedUser = value;
    notifyListeners();
  }

  changeTargetScreen(int value) {
    targetScreen = value;
    notifyListeners();
  }

  changeNewEvent(bool value) {
    newEvent = value;
    notifyListeners();
  }

  changeNewTrxn(bool value) {
    newTrxn = value;
    notifyListeners();
  }

  changeNewUser(bool value) {
    newUser = value;
    notifyListeners();
  }

  changeNewCompany(bool value) {
    newCompany = value;
    notifyListeners();
  }
}

现在,我如何以及在哪里实现ref.read和watch?
下面是UserProfileScreen类:

class UserProfileScreen extends ConsumerStatefulWidget {
  static const String id = 'user_profile_screen';
  final Users? users;

  UserProfileScreen([this.users]);

  @override
  _UserProfileScreenState createState() => _UserProfileScreenState();
}

class _UserProfileScreenState extends ConsumerState<UserProfileScreen> {
  final globalProvider =
            Provider.of<GlobalsProvider>(context, listen: false);
  final _db = FirebaseFirestore.instance;

  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  final fNameController = TextEditingController();
  final lNameController = TextEditingController();
  final address1Controller = TextEditingController();
  final address2Controller = TextEditingController();
  final cityController = TextEditingController();
  final stateController = TextEditingController();
  final zipController = TextEditingController();
  final cellPhoneController = TextEditingController();
  final officePhoneController = TextEditingController();
  final companyController = TextEditingController();
  final mlsController = TextEditingController();

  @override
  
  // Dispose of all the TextControllers when done using them so they don't consume memory
  @override
  void dispose() {
  }

  String? _currentUserState = globals.currentAgentState; <<< How would I set this variable using the provider?
  String? _currentCompanyState;
  String? _currentCompany;
  String? _currentMls;

  getCurrentAgentProfile() async {

    if (globals.newUser == true) { <<<  How to replace global with provider?
      final DocumentSnapshot currentAgencyProfile =
          await companyRef.doc(globals.agencyId).get();<<<  How to replace global with provider?

      emailController.text = "";
      fNameController.text = "";
      lNameController.text = "";
      address1Controller.text = currentAgencyProfile['address1'];
      address2Controller.text = currentAgencyProfile['address2'];
      cityController.text = currentAgencyProfile['city'];
      zipController.text = currentAgencyProfile['zipCode'].toString();
      cellPhoneController.text = currentAgencyProfile['cellPhone'];
      officePhoneController.text = currentAgencyProfile['officePhone'];
      companyController.text = currentAgencyProfile['name'];
      // Updates State
      Future.delayed(Duration.zero, () {
        final agentProvider =
            Provider.of<AgentProvider>(context, listen: false);
        agentProvider.loadValues(Users());
      });
    } else {
      final DocumentSnapshot currentAgentProfile =
          await usersRef.doc(globals.currentAgentId).get();

      // existing record
      // Updates Controllers
      emailController.text = currentAgentProfile["email"] ?? "";
      fNameController.text = currentAgentProfile['fName'] ?? "";
      lNameController.text = currentAgentProfile['lName'] ?? "";
      address1Controller.text = currentAgentProfile['address1'] ?? "";
      address2Controller.text = currentAgentProfile['address2'] ?? "";
      cityController.text = currentAgentProfile['city'] ?? "";
      //stateController.text = currentAgentProfile.data()['state'];
      _currentUserState = currentAgentProfile['state'] ?? "";
      if (currentAgentProfile.get('state') == "" ||
          currentAgentProfile.get('state') == null) {
        _currentCompanyState = globals.currentAgentState;
      } else {
        _currentCompanyState = currentAgentProfile['state'] ?? "";
      }
      ;
      zipController.text = currentAgentProfile['zipCode'].toString() ?? "";
      cellPhoneController.text = currentAgentProfile['cellPhone'] ?? "";
      officePhoneController.text = currentAgentProfile['officePhone'] ?? "";
      companyController.text = currentAgentProfile['agency'] ?? "";
      mlsController.text = currentAgentProfile['mls'] ?? "";
      // Updates State
      Future.delayed(Duration.zero, () {
        final userProvider =
            Provider.of<UserProvider>(context, listen: false);
        userProvider.loadValues(widget.users!);
      });
    }
  }

  List<DropdownMenuItem<String>>? _dropDownState;

  List<DropdownMenuItem<String>> getDropDownState() {
    List<DropdownMenuItem<String>> items = [];
    for (String state in globals.states/* as Iterable<String>*/) {
      items.add(DropdownMenuItem(
          value: state,
          child: Text(
            state,
          )));
    }
    return items;
  }

  void changedDropDownState(String? selectedState) {
    setState(() {
      _currentUserState = selectedState;
      globals.selectedAgentState = selectedState;
      globals.currentAgentState = selectedState;
    });
  }

  void changedDropDownAgency(String? selectedAgency) {
    setState(() {
      _currentCompany = selectedAgency;
      globals.selectedAgency = selectedAgency;
      globals.currentAgencyName = selectedAgency;
    });
  }

  void changedDropDownMls(String? selectedMls) {
    setState(() {
      _currentMls = selectedMls;
      globals.mlsId = selectedMls;
    });
  }

  @override
  void initState() {
    getCurrentAgentProfile();
    if (globals.currentAgentState == "" || globals.currentAgentState == null) {
      _currentUserState = globals.currentAgencyState;
    } else {
      _currentUserState = globals.currentAgentState;
    }
    ;
    _currentCompany = globals.agencyId;
    _currentCompanyState = globals.currentAgencyState;
    super.initState();

    _dropDownState = getDropDownState();
  }

  @override
  Widget build(BuildContext context) {
    // Get the stream of agents created in main.dart
    final agentProvider = Provider.of<AgentProvider>(context);
    final _firestoreService = FirestoreService();

    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.asset('assets/images/Appbar_logo.png',
                fit: BoxFit.cover, height: 56),
          ],
        ),
      ),
      backgroundColor: Colors.white,
      body: SafeArea(
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              children: <Widget>[
                const Text(
                  'Agent Profile',
                  style: TextStyle(
                    fontSize: 30,
                  ),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                // Email entry text field
                TextField(
                  controller: fNameController,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changefName(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'First Name', labelText: 'First Name'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: lNameController,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changelName(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'Last Name', labelText: 'Last Name'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                Container(
                  child: StreamBuilder(
                      stream: _db.collection('agency').snapshots(),
                      builder: (BuildContext context, AsyncSnapshot snapshot) {
                        if (snapshot.data == null) {
                          return const Center(
                            child: CircularProgressIndicator(),
                          );
                        } else {
                          return DropdownButton<String>(
                            hint: const Text("Select Agency"),
                            value: _currentCompany,
                            onChanged: changedDropDownAgency,
                            items: snapshot.data.docs
                                .map<DropdownMenuItem<String>>((document) {
                              return DropdownMenuItem<String>(
                                value: document.id,
                                child: Text(document.data()['name']),
                              );
                            }).toList(),
                          );
                        }
                      }),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: address1Controller,
                  keyboardType: TextInputType.text,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeaddress1(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'Address 1', labelText: 'Address 1'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: address2Controller,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeaddress2(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'Address 2', labelText: 'Address 2'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: cityController,
                  keyboardType: TextInputType.emailAddress,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changecity(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'City', labelText: 'City'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                DropdownButton(
                  value: _currentUserState,
                  items: _dropDownState,
                  hint: const Text('Choose State'),
                  onChanged: changedDropDownState,
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  controller: zipController,
                  keyboardType: TextInputType.number,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changezipCode(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'Zip Code', labelText: 'Zip Code'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  inputFormatters: [maskFormatter],
                  controller: cellPhoneController,
                  keyboardType: TextInputType.phone,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changecellPhone(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'Cell Phone', labelText: 'Cell Phone'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                TextField(
                  inputFormatters: [maskFormatter],
                  controller: officePhoneController,
                  keyboardType: TextInputType.phone,
                  textAlign: TextAlign.center,
                  onChanged: (value) {
                    agentProvider.changeofficePhone(value);
                    if (globals.currentAgentState == "" ||
                        globals.currentAgentState == null) {
                      _currentUserState = globals.currentAgencyState;
                    } else {
                      _currentUserState = globals.currentAgentState;
                    }
                    ;
                  },
                  decoration: const InputDecoration(
                      hintText: 'Office Phone', labelText: 'Office Phone'),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                Container(
                  child: StreamBuilder(
                      stream: _db.collection('mls')
                          .where('mlsState', isEqualTo: globals.currentAgentState).snapshots(),
                      builder: (BuildContext context, AsyncSnapshot mlsSnapshot) {
                        if (mlsSnapshot.data == null) {
                          return const Center(
                            child: CircularProgressIndicator(),
                          );
                        } else {
                          return DropdownButton<String>(
                            hint: const Text("Select MLS"),
                            value: _currentMls,
                            onChanged: changedDropDownMls,
                            items: mlsSnapshot.data.docs
                                .map<DropdownMenuItem<String>>((document) {
                              return DropdownMenuItem<String>(
                                value: document.id,
                                child: Text(document.data()['mlsName']),
                              );
                            }).toList(),
                          );
                        }
                      }),
                ),
                const SizedBox(
                  height: 8.0,
                ),
                RoundedButton(
                  title: 'Save',
                  colour: Colors.blueAccent,
                  onPressed: () async {
                    setState(() {
                      showSpinner = true;
                    });
                    try {
                      agentProvider.saveAgent();
                      globals.currentAgentName = fNameController.value.text +
                          ' ' +
                          lNameController.value.text;
                      globals.currentAgentState = _currentUserState;
                      await _firestoreService.saveDeviceToken();
                      globals.targetScreen = 0;
                      Navigator.of(context).pushReplacement(MaterialPageRoute(
                          builder: (context) => MainScreen()));

                      setState(() {
                        showSpinner = false;
                      });
                    } catch (e) {
                      // todo: add better error handling
                      print(e);
                    }
                  },
                ),
                const SizedBox(
                  height: 8.0,
                ),

                (widget != null)
                    ? RoundedButton(
                        title: 'Delete',
                        colour: Colors.red,
                        onPressed: () async {
                          setState(() {
                            showSpinner = true;
                          });
                          try {
                            agentProvider.deleteAgent(globals.currentUid);
                            globals.targetScreen = 2;
                            Navigator.push(
                                context,
                                MaterialPageRoute(
                                    builder: (context) => MainScreen()));
                            //Navigator.pushNamed(
                            //    context, AgentDashboardScreen.id);

                            setState(() {
                              showSpinner = false;
                            });
                          } catch (e) {
                            // todo: add better error handling
                            print(e);
                          }
                        },
                      )
                    : Container()
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          setState(() {
            showSpinner = true;
          });
          try {
            agentProvider.saveAgent();
            globals.targetScreen = 0;
            await _firestoreService.saveDeviceToken();
            Navigator.push(
              context,
              new MaterialPageRoute(
                builder: (context) => MainScreen(),
              ),
            );
            setState(() {
              showSpinner = false;
            });
          } catch (e) {
            // todo: add better error handling
            print(e);
          }
        },
        backgroundColor: kPrimaryColor,
        child: const Icon(
          Icons.assignment_turned_in_outlined,
          color: Colors.blueAccent,
        ),
      ),
    );
  }
}

我很抱歉,我在这里是如此愚蠢,但这里有一些问题,我仍然有:
1.如何将提供程序添加到UserProfileScreen类?
1.如何使用提供程序从提供程序获取值并替换全局变量?
1.如何以及在哪里放置ref.read方法?
我真的很感激你的回答和帮助,但我还是不明白。

m1m5dgzv

m1m5dgzv1#

你需要把这个变量尽可能地分成几个类或提供程序,当你调用notifylisteners()或者你观察并改变它的时候,它会重建所有的监听器,即使它们不需要重建。
我的建议是:

class MyGlobalProvider {
  //this is just helper class, private its constructor
  MyGlobalProvider._();
  
  static final currentUid = StateProvider<String?>((ref) => null);
  static final currentUEmail = StateProvider<String?>((ref) => null);

  static final companyID = StateProvider<String?>((ref) => null);

  static final targetScreen = StateProvider<String?>((ref) => null);

  static final isNewUser = StateProvider<bool?>((ref) => null);
  static final isNewCompany = StateProvider<bool>((ref) => false);
}

一次读取更新:

void updateUID(WidgetRef ref,String newUID){
    ref.read(MyGlobalProvider.currentUid.notifier).state = newUID;
    // or if you need previous state use update method
    ref.read(MyGlobalProvider.currentUid.notifier).update((previousUID)=> newUID);
  }

手表:

Consumer(
  builder: (context, ref, child){
    final uid = ref.watch(MyGlobalProvider.currentUid);
    return Text(uid ?? '');
  },);

相关问题