How To Call values from provider Flutter - flutter

I have this provider which retrieves data from a shared preference.
class AuthProvider with ChangeNotifier {
String? usertoken = '';
String? tokenExpiry = '';
Future<AuthResponse> getuserdata() async {
SharedPreferences _preferences = await SharedPreferences.getInstance();
String? userdata = _preferences.getString('userData');
var usersData = jsonDecode(userdata!);
AuthResponse authResponse = AuthResponse.fromJson(usersData);
usertoken = authResponse.token;
print('Test in provider : $usertoken');
notifyListeners();
return authResponse;
}
}
How can i get the values i need from the provider? to say another function?
getinterestList() async {
final test = Provider.of<AuthProvider>(context).usertoken; //gets Error
print(test);
}

Related

This expression has a type of 'void' so its value can't be used - Flutter

import 'package:demo_app/services/api.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AuthProvider extends ChangeNotifier{
bool isAuthenticated = false;
late String token;
late ApiService apiService;
AuthProvider() {
init();
}
Future<void> init() async {
token = await getToken();
if (token.isNotEmpty) {
isAuthenticated = true;
}
apiService = ApiService(token);
notifyListeners();
}
Future<void> register(String name, String email, String password, String passwordConfirm, String deviceName) async{
token = await apiService.register(name, email, password, passwordConfirm, deviceName);
isAuthenticated = true;
setToken();
notifyListeners();
}
Future<void> logIn(String email, String password, String deviceName) async{
token = await apiService.login(email, password, deviceName);
isAuthenticated = true;
setToken();
notifyListeners();
}
Future<void> logOut() async{
token = '';
isAuthenticated = false;
setToken();
notifyListeners();
}
Future<void> setToken() async{
final pref = await SharedPreferences.getInstance();
pref.setString('token', token);
}
Future<void> getToken() async{
final pref = await SharedPreferences.getInstance();
pref.getString('token') ?? '';
}
}
token = await getToken();
gives this error
This expression has a type of 'void' so its value can't be used.
Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void.
Any clue on solving this issue?
Try the following code:
Future<void> init() async {
token = await getToken();
if (token.isNotEmpty) {
isAuthenticated = true;
}
apiService = ApiService(token);
notifyListeners();
}
Future<String> getToken() async {
final pref = await SharedPreferences.getInstance();
final token = pref.getString("token") ?? "";
return token;
}

displaying only the current user data

I protected data_service with current user to only display the current user's habits.
data_service.dart:
class DataService {...
late final Database db;
Users? _user;
late final StreamData<Map<int, Habit>> habits;
Future<void> init() async {
db = await HabitsDb.connectToDb();
habits = StreamData(initialValue: await _getAllHabits(), broadcast: true);
}
String get userEmail => AuthService.firebase().currentUser!.email;
Future<Map<int, Habit>> _getAllHabits() async {
getOrCreateUser(email: userEmail); //issue
final habits = await _getAllHabitsFromDb();
final map = Map<int, Habit>();
final currentUser = _user;
print(currentUser);
for (final habit in habits) {
if (currentUser != null) {
print(currentUser.id);
print(habit.userId);
if (habit.userId == currentUser.id) {
map[habit.id] = habit;
}
}
//map[habit.userId] = currentUser?.id;
}
return map;
}
Future<List<Habit>> _getAllHabitsFromDb() async {
final habitsMap = await HabitsDb.getAllHabits(db);
final habitsList = habitsMap.map((e) => Habit.fromDb(e)).toList();
return habitsList;
}
Future<Users> getOrCreateUser({
required String email,
bool setAsCurrentUser = true,
}) async {
try {
//we found the user
final user = await getUser(email: email);
if (setAsCurrentUser) {
_user = user;
}
print(_user?.email);
return user;
} on CouldNotFindUser {
//we didn't find the user
final createdUser = await createUser(email: email);
if (setAsCurrentUser) {
_user = createdUser;
}
return createdUser;
} catch (e) {
rethrow;
}
}
...}
in main class:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
final dataService = DataService();
await dataService.init();
GetIt.I.registerSingleton(dataService);
... }
StreamData class:
class StreamData<T> {
List<Habit> _notes = [];
User? _user;
late final StreamController<T> _controller;
Stream<T> get stream => _controller.stream;
late T _value;
T get value => _value;
StreamData({required T initialValue, bool broadcast = true}) {
if (broadcast) {
_controller = StreamController<T>.broadcast();
} else {
_controller = StreamController<T>();
}
_value = initialValue;
}
the problem is that the line getOrCreateUser(email: userEmail); is only called once and it does not work when I switch user and I need to Hot Restart to fix it. I think using Futurebuilder will fix it. but if yes, how do I use it when there is a need to call dataService.init at the beginning of the main?
Since your getOrCreateUser function is declared as async, you'll want to use await when you call it in _getAllHabits:
await getOrCreateUser(email: userEmail)
This ensures the getOrCreateUser code has completed before the rest of the code in _getAllHabits (that depends on the result of getOrCreateUser) executes.

is there way to get a particular data which have been saved using shared preference?

#i Saved all my user data using shared preference to perform autologin and it works well data is saved
token = responseData['token'];
userEmail = responseData['user_email'];
userNicename = responseData['user_nicename'];
userDisplayName = responseData['user_display_name'];
userAddress = responseData['user_address'];
userContact = responseData['user_contact'];
userId = responseData['user_id'];
userDisplayUrl = responseData['user_display_url'];
notifyListeners();
SharedPreferences prefs = await SharedPreferences.getInstance();
final userData = jsonEncode({'token':token,'user_email':userEmail,'user_nicename':userNicename,'user_display_name':userDisplayName,'user_address':userAddress,'user_contact':userContact,'user_id':userId,'user_display_url':userDisplayUrl});
prefs.setString('userData',userData);
#Data is saved in this manner
{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvc3dlZXQtYXJkaW5naGVsbGkuMy0xMDgtMTM4LTIwNi5wbGVzay5wYWdlIiwiaWF0IjoxNjQyMzMwNzQyLCJuYmYiOjE2NDIzMzA3NDIsImV4cCI6MTY0MjkzNTU0MiwiZGF0YSI6eyJ1c2VyIjp7ImlkIjoiMjgifX19.2jZEu-QNL3UxRiFSgVE728bF_cl_CZd0VJLT1f5HfCc","user_email":"sauravadhikari404#gmail.com","user_nicename":"sauravadhikari404","user_display_name":"SauravAdhikari404","user_address":null,"user_contact":null,"user_id":"28","user_display_url":""}
#now i wanna access single single data like i wanna get that user_id only or user_email only but i dont know how to do it i tried like this
String? userData;
#override
void initState(){
// TODO: implement initState
getUserId();
super.initState();
}
void getUserId()async{
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
userData = prefs.getString("userData");
print(userData);
});
}
#as i mentioned above all my data is comming in userData but now i wanna fetch my user_id only or user_email but i am unable to
Use jsonDecode to convert it to a Map:
Like so:
setState(() {
var userId = jsonDecode(prefs.getString("userData"))["user_id"];
print(userId);
});
To handle the null case:
String? userDataString = prefs.getString("userData");
if(userDataString != null){
var userId = jsonDecode(userDataString)["user_id"];
var email = jsonDecode(userDataString)["user_email"];
}

Flutter Null Safe Config Class with shared_preferences

In flutter 1.x, I implemented a Config class using the Flutter shared_preferences package; the code looks like this:
import 'package:shared_preferences/shared_preferences.dart';
class Config {
static final Config _config = Config._internal();
factory Config() => _config;
final accessTokenKey = 'accessToken';
String _accessToken;
SharedPreferences prefs;
Config._internal() {
loadData();
}
void loadData() async {
prefs = await SharedPreferences.getInstance();
_accessToken = prefs.getString(accessTokenKey) ?? '';
}
String get accessToken {
return _accessToken;
}
set accessToken(String accessToken) {
_accessToken = accessToken;
_saveString(accessTokenKey, accessToken);
}
_saveString(String key, String value, {String printValue = ''}) {
String printVal = printValue.length > 0 ? printValue : value;
prefs.setString(key, value);
}
}
I’m creating a new project in Flutter 2.x and trying to use the same code, but due to changes associated with null safety I’m having some difficulty getting the updated code just right.
The updated documentation for the package says to initialize the _prefs object like this:
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Then create a local prefs object using:
final SharedPreferences prefs = await _prefs;
This is fine, but I don’t want to have to make every class method that uses shared_preferences async then recreate the variable. At the same time I can’t create it as a class variable without initializing it first. Can someone please show me a cleaner way to do this, or do I just have to redeclare it every time I use it?
Also, how do I initialize the config object in my other classes? In my 1.x code, I would just do this:
final Config config = new Config();
then start accessing the properties of the config object. How do I initialize it with all of the async code in the class now?
Here’s where the updated code is today:
import 'package:shared_preferences/shared_preferences.dart';
import '../models/device.dart';
class Config {
static final Config _config = Config._internal();
factory Config() => _config;
final accessTokenKey = 'accessToken';
String _accessToken = '';
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
Config._internal() {
print('Config constructor');
loadData();
}
Future<void> loadData() async {
final SharedPreferences prefs = await _prefs;
_accessToken = prefs.getString(accessTokenKey) ?? '';
}
String get accessToken {
return _accessToken;
}
set accessToken(String accessToken) {
_accessToken = accessToken;
_saveString(accessTokenKey, accessToken);
}
_saveString(String key, String value, {String printValue = ''}) {
String printVal = printValue.length > 0 ? printValue : value;
print('Config: _saveString("$key", "$printVal")');
final SharedPreferences prefs = await _prefs;
prefs.setString(key, value);
}
}
You can get instance of SharedPreferences as static field in init method:
static SharedPreferences? _prefs; //or: static late SharedPreferences _prefs;
static init() async {
_prefs = await SharedPreferences.getInstance();
}
And call init() somewhere like in build() method of first widget run, for once.Now you can use _prefs everywhere as you want.
If I want to show you a complete class to use SharedPreferences, it looks like this:
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferencesRepository {
static SharedPreferences? _prefs;
static init() async {
_prefs = await SharedPreferences.getInstance();
}
static putInteger(String key, int value) {
if (_prefs != null) _prefs!.setInt(key, value);
}
static int getInteger(String key) {
return _prefs == null ? 0 : _prefs!.getInt(key) ?? 0;
}
static putString(String key, String value) {
if (_prefs != null) _prefs!.setString(key, value);
}
static String getString(String key) {
return _prefs == null ? 'DEFAULT_VALUE' : _prefs!.getString(key) ?? "";
}
static putBool(String key, bool value) {
if (_prefs != null) _prefs!.setBool(key, value);
}
static bool getBool(String key) {
return _prefs == null ? false : _prefs!.getBool(key) ?? false;
}
}
I hope this useful for you.
If you need to wait for some async work to finish before getting an instance of a class, consider using a static method (not a factory constructor, since constructors must always return the base type).
You can use late fields to allow them to be non-null before you initialize them:
class Config {
late String _accessToken;
String get accessToken => _accessToken;
Config._(); // private constructor to prevent accidental creation
static Future<Config> create() async {
final config = Config();
final preferences = await SharedPreferences.getInstance();
config._accessToken = await preferences.getString('<your key>');
return config;
}
}
If you want to make sure this is initialized before running your app, you can initialize it in your main() method before you call runApp() to give control to the Flutter framework:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); // make sure all plugins loaded etc.
final config = await Config.create();
print(config.accessToken);
runApp(MyApp());
}

Access other Class method in Flutter/dart

I was working on login with preference. Everything is working fine when I wrote all code in main.dart.
Problem:
When I create separate class on MySharePref then I am getting some error.
MySharePref.dart
import 'package:first_app/UserModel.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SharePrefClass {
void _saveData(UserModel model) async{
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString("Username",model.userName);
await prefs.setString("Password", model.password);
}
Future<UserModel> _getData() async{
SharedPreferences preferences = await SharedPreferences.getInstance();
String username = preferences.getString("Username");
String password = preferences.getString("Password");
UserModel model = UserModel(username,password);
return model;
}
}
I want to access these both functions in main.dart:
_checkLogin() async {
UserModel userModel = new UserModel(
userNameEditText.text , passwordEditText.text);
SharePrefClass mySharedPref = new SharePrefClass();
final UserModel returnModel = mySharedPref._getData() ;
if(returnModel.userName == ""){
print("No data");
}else{
print("else executed");
}
}
I am getting error:
The prefix "_" means private field in dart.
Change the method name _getData() to getData() will let you can access this method in main.dart