我很难在我的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方法?
我真的很感激你的回答和帮助,但我还是不明白。
1条答案
按热度按时间m1m5dgzv1#
你需要把这个变量尽可能地分成几个类或提供程序,当你调用
notifylisteners()
或者你观察并改变它的时候,它会重建所有的监听器,即使它们不需要重建。我的建议是:
一次读取更新:
手表: