Reputation: 1843
[Edited] I have this application with multilevel user application where I have functions based on roles. Currently, I am saving user response in shared preferences and fetching it by getting it's instance whenever I need it. And also, I am using different screens and different widgets for each role. But there has to be a better way to do it. I am so confused with singleton pattern and making global variables in dart.
Here's my code:
void main() {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences.getInstance().then((prefs) {
var user=prefs.getString("role");
runApp(MultiProvider(
providers: [
ChangeNotifierProvider<RoleNotifier>(
create: (_) => RoleNotifier(user),
),
],
child: MyApp(),
));
});
}
void setRole(String role) async {
Provider.of<RoleNotifier>(context, listen:false).setUser(role);
await SharedPreferences.getInstance().then((prefs){
prefs.setString("role", role);
});
}
_login() async {
try {
setState(() {
_isbusy = true;
});
var data = {"username": _emailc.text, "password": _pass.text};
var response = await CallApi().postData(data, 'login');
SharedPreferences local = await SharedPreferences.getInstance();
var res = response.data;
print(res);
if (res['success']) {
local.setString('token', res['data']['token']);
if (res['data']['role'] == 'admin') {
setRole(res['data']['role']);
local.setString('info', json.encode(res['data']));
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => AdminDashBoard()));
} else if (res['data']['role'] == 'dev') {
setRole(res['data']['role']);
local.setString('post', res['data']['role']);
local.setString('info', json.encode(res['data']));
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => DevDashBoard()));
} else if (res['data']['role'] == 'user') {
setRole(res['data']['role']);
local.setString('post', res['data']['role']);
local.setString('info', json.encode(res['data']));
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => UserDashBoard()));
}
} else {
print('error');
setState(() {
_isbusy = false;
});
showSimpleFlushbar(context, "An Error Occurred!");
}
} on DioError catch (e) {
print(e);
setState(() {
_isbusy = false;
});
print(e.response.data);
print(e.response.headers);
print(e.response.request);
showSimpleFlushbar(context,
"Login Failed! Please Check your credentials and try again.");
}
}
And to access the variables:
SharedPreferences.getInstance().then((prefs) {
var data = jsonDecode(prefs.getString("info"));
setState(() {
email = data['email'];
post = data['role'];
});
});
The problem is, I have to run this on initState in every screen and there is a delay in fetching data which throws an exception for small time. I just figured out this is working.
(Provider.of<RoleNotifier>(context).getUser()=="admin")?AdminWidget():SizedBox(),
Now I can access the data from anywhere using provider. But is there any better way to do this? I've heard a lot about singleton pattern and in my case even though it works, it seems like I am doing something wrong. Like I am listening to the value that is static immediately after login is completed.
Upvotes: 1
Views: 2048
Reputation: 11651
SharedPreferences prefs;// file level global variable
main(){
SharedPreferences.getInstance().then((p)=>prefs = p);
// do whatever
runApp(MyApp());
}
Now, don't use SharedPreferences.getInstance()
when needed but use the global variable
created.
Like
prefs.getString('name');
or
prefs.setString('foo','bar');
For example
class Foo extends StatelessWidget{
Widget build(context){
var name = prefs.getString('name');// don't use var prefs = await SharedPreferences.getInstance();
return Text("name is $name");
}
}
Upvotes: 3
Reputation: 123
Why not create a User class and extend it with Provider?
Then based on the Consumers to build dynamic widgets you can pump out what ever you want based on the User.role for the selected user.
In your Singleton you can add a Singleton().selectedUser var and once a user logs in or what ever process they follow you can assign it to that. Use this selectedUser var for your Provider.value.
If you need example code let me know.
Upvotes: 0