Store data in dart/flutter - flutter

I am coding a to-do list app in flutter but every time I close the app, all my to-do's are gone, and none of them are stored. How do I stop them from disappearing every time I close the app?

Use sqlite or files. Please refer documentation on cookbooks for either approach.
https://docs.flutter.dev/cookbook/persistence
Your other option is to use an external database over the internet

To persist your data (todo list) you can either
store data on the users device
You can do this by using a local databases like sqflite, sqfentity, shared_preferences etc
or store the data on the server
Using this option you can either spin up your own server or use some quick serverless solutions like supabase or cloud firestore from firebase.

I recommend hive it’s very easy to use and it’s lightweigh.

In addition with all the other propositions, you can try Isar, which is a NoSQL local database that can be used for all platforms:
https://isar.dev/tutorials/quickstart.html
https://pub.dev/packages/isar

Apps generally store data in temporary storage which destroyed every time yo close the app. in order to save data permanently, you could use sqflite database or shared_preferences database
if you want use shared_preferences, you can do this:
first make class that call StorageManager:
import 'package:shared_preferences/shared_preferences.dart';
class StorageManager {
static Future<bool> saveData(String key, dynamic value) async {
final prefs = await SharedPreferences.getInstance();
await prefs.reload();
if (value is int) {
prefs.setInt(key, value);
return true;
} else if (value is String) {
prefs.setString(key, value);
return true;
} else if (value is bool) {
prefs.setBool(key, value);
return true;
} else {
return false;
}
}
static Future<dynamic> readData(String key) async {
final prefs = await SharedPreferences.getInstance();
await prefs.reload();
dynamic obj = prefs.get(key);
return obj;
}
static Future<bool> deleteData(String key) async {
final prefs = await SharedPreferences.getInstance();
return prefs.remove(key);
}
static Future<void> reloadSharedPreferences() async {
final prefs = await SharedPreferences.getInstance();
await prefs.reload();
}
}
then use it like this:
when you want save some thing in storage call this:
await StorageManager.saveData('some unique key', your int or string or bool value);
when you want read from storage:
var result = await StorageManager.readData('some unique key');
if (result != null) {
// use your value
} else {
// this means there is no result
}

Related

How to save prefs to different scopes in Flutter?

I am trying to use shared prefs to store App Data and User Data differently, like this :
{
"APP_DATA": {
"banners": "{\"success\":true,\"data\":{}}",
"gameList": "{\"success\":true,\"data\":{}}"
},
"USER_DATA":
{
"emailVerified": "N",
"userName": "97144554455",
"playerToken": "W_8zUx3UCmFPeECjhhjhHhnnsajknHxAM0",
"idVerified": "UPLOADED",
"playerId": "412904",
"bankList": "{\"84\":\"African Bank\",\"5\":\"FNB : First National Bank\"}",
"unreadMsgCount": "0"
}
}
But whenever I update any value in "APP_DATA" or "USER_DATA", it deletes the previous value and updates new value. Example : After adding "banners" and "gamesList" to my APP_DATA, I only see "gamesList" because it is overriding the "banners" value.
MySharedPreferences.instance.setAppStringValue(
"banners", jsonEncode(bannersModel),
);
MySharedPreferences.instance.setAppStringValue(
"gamesList", jsonEncode(gamesListModel),
);
This is the function I'm using
setAppStringValue(String key, String value) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
myPrefs.setString("APP_DATA", jsonEncode({key: value}));
}
How to solve this issue?
What is happening is that you are overriding the APP_DATA key with a whole new value (encoded String) which results in the previous data to be lost.
If you want to keep the same structure, this is, having a key for APP_DATA and other for USER_DATA, both having their own data, you'll need to fetch the previous stored data and append the new one into it so you make sure you don't lose it.
setAppStringValue(String key, String value) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
final String storedData = myPrefs.get('APP_DATA');
final Map newData = {key: value};
try {
// Has previous data, decode it and append into the new one
if (storedData != null) {
newData.addAll(jsonDecode(storedData));
}
} catch (ex) {
print('Couldn\'t parse the stored data: $ex');
}
myPrefs.setString('APP_DATA', jsonEncode(newData));
}
When using shared preferences, it uses the unique key to recognise the value of the corresponding data. When you are writing data to the key 'APP_DATA' it will overwrite the entire string value. To change one value without overwriting the rest, you should save it in different keys. Like so,
setAppStringValue(String key, String value) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
myPrefs.setString("banner", jsonEncode({key: value}));
}
setAppStringValue(String key, String value) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
myPrefs.setString("gamesList", jsonEncode({key: value}));
}

how to retrieve a value from shared preferences instantly? - FLUTTER

I'm trying to show a page as an initial login, this is only displayed when my switch value is set to true.
The switch value is stored with shared preferences but when I open the application it is not recovered, only after an application update is it actually recovered. how can i get it to be recovered instantly when i open my application?
below the code:
Future<bool> saveSwitchState(bool value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool("switched", value);
print('Switch Value saved $value');
return prefs.setBool("switched", value);
}
Future<bool> getSwitchState() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
SettingsPage.switched = prefs.getBool("switched")!;
print(SettingsPage.switched);
return SettingsPage.switched;
}
on another page then the value that is actually recovered:
if(AuthPage.authenticated == false && SettingsPage.switched == true ) {
yield ProfileNoAuth();
return; }
you can use dependency injection follow these steps :
get it package
create a Separate dart containing the following code file like this:
GetIt locator = GetIt.instance;
Future<void> setupLocator() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
locator.registerLazySingleton<SharedPreferences>(() => sharedPreferences);
}
call the setupLocator() method and wait for it in your main function
void main() async {
await setupLocator();
runApp(App());
}
access SharedPreferences Instance from anywhere like this:
locator();
now the SharedPreferences Instance if available anywhere in your project
please note that you dont have to wait for getting the Instance anymore, because you have only one Instance sharable across the application
bool getSwitchState() {
final prefs = locator<SharedPreferences>();
SettingsPage.switched = prefs.getBool("switched")!;
print(SettingsPage.switched);
return SettingsPage.switched;
}

How to save data of type bool in shared_preferences flutter

I created a separate calss page to working with shared preferences from all the different application pages. Save or edit data. I can save String data with ease, but I am facing a problem saving data of type bool. I try to save data of type bool to store the status of the user logged in or not. I searched for solutions for a long time, but couldn't find.
full code:
import 'package:shared_preferences/shared_preferences.dart';
class MyPreferences {
static const ID = "id";
static const STATE = "state";
static final MyPreferences instance = MyPreferences._internal();
static SharedPreferences _sharedPreferences;
String id = "";
String state = "";
MyPreferences._internal() {}
factory MyPreferences() => instance;
Future<SharedPreferences> get preferences async {
if (_sharedPreferences != null) {
return _sharedPreferences;
} else {
_sharedPreferences = await SharedPreferences.getInstance();
state = _sharedPreferences.getString(STATE);
id = _sharedPreferences.getString(ID);
return _sharedPreferences;
}
}
Future<bool> commit() async {
await _sharedPreferences.setString(STATE, state);
await _sharedPreferences.setString(ID, id);
}
Future<MyPreferences> init() async {
_sharedPreferences = await preferences;
return this;
}
}
Can somebody help me to make bool data.
thank you
Just add a couple methods to your class.
void updateLoggedIn(bool value) {
_sharedPreferences.setBool('logged_in', value);
}
bool isLoggedIn() => _sharedPreferences.getBool('logged_in') ?? false;
Then on login just run
MyPreferences.instance.updateLoggedIn(true)
And the same thing passing in false on logout.
Then whenever you want to check logged in status just run
if(MyPreferences.instance.isLoggedIn()) {
// whatever needs to happen
}

Safe to use the same instance of shared_preferences in flutter

I have a simple question regering the shared_preferences package in flutter.
Is it safe to get an instance of SharedPreferences and store that for future use or is it best to always get a new reference each time?
To clarify, which of these two are the proper or best way of doing it?
SharedPreferences preferences;
void init() async {
preferences = await SharedPreferences.getInstance();
}
void setValue(String key, String value) async{
await preferences.setString(key, value);
}
void setValue(String key, String value) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setString(key, value);
}

Flutter SharedPreferences getInstance return null

Although I set the _sharedPreferences in the constructor, it gets null in getUsername. I don't know missing what:
class PreferencesProvider {
SharedPreferences _sharedPreferences;
PreferencesProvider() {
SharedPreferences.getInstance().then((prefs) => _sharedPreferences = prefs);
}
String getUsername() {
return _sharedPreferences.getString("Username");
}
String getX() {
return _sharedPreferences.getString("X");
}
String getY() {
return _sharedPreferences.getString("Y");
}
String getZ() {
return _sharedPreferences.getString("Z");
}
}
alternatively it didn't work either:
class LoginProvider {
SharedPreferences _sharedPreferences;
LoginProvider._internal();
static final LoginProvider _instance = LoginProvider._internal();
factory LoginProvider() {
_instance.initPreferences();
return _instance;
}
initPreferences() async {
_sharedPreferences = await SharedPreferences.getInstance();
}
I want to use this in MaterialApp:
initialRoute: PreferencesProvider().isLoggedIn() ? "MainPage" : "LoginPage"
Edit: I know I should use await. But then keyword isn't same? I don't want to wait the instance again for all returns. In the other hand, I can't use await in initialRoute.
The way i manage to login the user for my application for the similar scenario is,
String startPage="LoginPage";
void main() {
SharedPreferences prefs = await SharedPreferences.getInstance();
String user=prefs.getString("Username");
if(user!=null && user.length>0){
startPage="MainPage";
}
runApp(MyApp());
}
Now, set your initialRoute as follow,
initialRoute: startPage,
This solution works in every scenario because i am fetching the data before the runApp() function in my application. Your application renders your initialPage after calling the runApp() function.
This is the best way to manage your login page based on data retrieval from the sharedpreferences as SharedPreferences takes time to fetch the data. Till the data is retrieved from sharedpreferences your build method gets completed its UI rendering.
While using preferences you should use Future, await and async
Future<String> getUsername() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String storeUserDetails = prefs.getString("Username");
return (storeUserDetails != null);
}
Hope this helps!
You need to wait a little bit for get username from shared preferences. getInstance is an async process.
Below code will work, because getString will work after getInstance
Future<String> getUsername() async {
_sharedPreferences = await SharedPreferences.getInstance();
return _sharedPreferences.getString("Username");
}
You need to modify your PreferencesProvider class