How can you store lists of Items in Flutter - flutter

How could you store something like that even when the app is closed in Flutter:
Class myList {
String id;
List<Item> list;
}
Class Item{
//Many property’s
}
I thought maybe I could do that with "sqflite", a flutter dependency, but I have no Idea how I could store there this List<Item>. Do you have any idea?
Btw: I need multiple of these "myList" instances.

You can store it using sqflite,hive or shared preferences.Try to save it under flutter shared preferences. These are two methods that you can use.
Using shared preferences
1)First create a shared preference instance
SharedPreferences prefs = await SharedPreferences.getInstance();
Then save the relevant data type.here you need to put a object list so add the list and convert it to the String using jsonEncode.
Map<String,List<Item>> map={mylist.id: mylist.list};
prefs.setString("itemList", json.encode(map));
Then you can retrieve data like this
Map<String,List<Item>> map=json.decode(prefs.getString("itemList")).asMap();
2)Using Hive
First Create the hive databse.you can put any name here
var box = Hive.box('myBox');
Then add the object in to that database
var myList = myList()
..id = your id here
..list = add list here;
var name = box.add(myList);
You can get anywhere this data list.
print(box.getAt(0));

You can try hive package. It is a lightweight local storage passage and it is a good idea to use hive because it has better benchmarks for reading and writes. You can search for the tutorial for the hive. or just read the documentation.

Related

Flutter Hive save custom object with list of custom objects gone after restarting app

I am using the Hive- Package in my project to store some data locally. That has been working fine so far, but now I am facing an issue:
I have a Custom-Class which also has a field with another Custom-Class:
part 'hive_vitals_interface.g.dart';
#HiveType(typeId: 1)
class HiveVitals extends HiveObject {
#HiveField(0)
String? id;
#HiveField(1)
DateTime? date;
#HiveField(2)
List<HiveDiscomfort> otherDiscomfort;
#HiveField(3)
List<HiveDiscomfort> mentalDiscomfort;
HiveVitals({
this.id,
this.date,
this.otherDiscomfort = const [],
this.mentalDiscomfort = const [],
});
}
And my HiveDiscomforts-Class:
part 'hive_discomfort_interface.g.dart';
#HiveType(typeId: 2)
class HiveDiscomfort extends HiveObject {
#HiveField(0)
String? title;
#HiveField(1)
int? intensity;
HiveDiscomfort({
this.title,
this.intensity,
});
}
I am trying to save HiveVitals like this:
static Future<void> addVitals(HiveVitals hiveVitals) async {
final vitalsBox = getVitalsBox();
await vitalsBox.put(hiveVitals.date!.toIso8601String(), hiveVitals);
}
And retrieve it like this:
static List<HiveVitals> getVitals() {
Box<HiveVitals> box = getVitalsBox();
List<HiveVitals> hiveVitals = box.values.toList();
return hiveVitals;
}
Problem:
I don't get any errors. In fact when saving my object and checking it in the debugger, everything is saved correctly. However when restarting the app, my List<HiveDiscomfort> fields are always empty again! But the rest of the HiveVitals-Fields are still saved correctly!?
What am I missing here? I don't get it... Any help is appreciated! Let me know if you need anything else!
Also opened an issue on Github.
I use this method and it works for me as List doesn't require registering an adapter:
await Hive.openBox<List>(bookmarks);
Add data like this:
boxValue.put(index, [
question.title,
question.options,
],
);
And you can access the data via ValueListenableBuilder.
If you're saying data is being saved and everything worked fine till you didn't restart the app. So the problem may be :
After restarting your app, you had may put a function that cleared all the data saved in Hive as soon as app starts.
Check this one.If like this will there then remove that line or function that clear all the data from hive DB.
Updated answer:
My previous solution got me thinking and I think I know why nested lists are not persisted.
It seems like hive is not checking for list equality and therefore never persist the changes, but uses the object as it is currently in memory. So, that is why as long as the application runs the object is correctly in memory, but when the app is closed hive does not persist the data as it thinks that the data (here the lists) never changed, even though they changed (this is my guess now without looking further into the code of the hive package).
So that means the solution would be to check for equality of the lists in the equals method. For this example it would be:
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is HiveVitals &&
runtimeType == other.runtimeType &&
id == other.id &&
date == other.date &&
listEquals(otherDiscomfort, other.otherDiscomfort) &&
listEquals(mentalDiscomfort, other.mentalDiscomfort);
For me this solution works.
Old answer:
I had the same issue...
I try to explain my solution based on this example.
Given an object HiveVitals hiveVitals = HiveVitals(), whenever I tried to add something to the nested list of my custom object like hiveVitals.otherDiscomfort.add(), it was saved but not persisted (it was gone whenever I restarted the app). What I did was the following when I wanted to add something to the nested list:
List<HiveDiscomfort> tempList = [...hiveVitals.otherDiscomfort];
tempList.add(newData);
hiveVitals.otherDiscomfort = tempList;
That worked for me, now my data is persisted.
I think this is a problem with the package because I have the same issue that everything works okay but with restarting the app the data disappears. So I asked the question at hive flutter github and no answers yet. So I ask u to open an issue at hive flutter github to let them know that this is a real problem we face it.
Here are a couple of hints about the issue which may be why the data is lost:
Hive FAQ: What happens if my app is killed? The worst thing that can happen is
that you lose the last entry if it isn't written completely yet. Hive
has built-in integrity checking and crash recovery and takes care of
everything.
Limitations: Keys have to be 32 bit unsigned integers or ASCII Strings with a max
length of 255 chars. The supported integer values include all
integers between -2^53 and 2^53, and some integers with larger
magnitude Objects are not allowed to contain cycles. Hive will not
detect them and storing will result in an infinite loop. Only one
process can access a box at any time. Bad things happen otherwise.
Boxes are stored as files in the user's app-directory. Common illegal
characters/symbols such as /%& should therefore be avoided.
The most likely cause though may be related to improper implementation of the Hive Relationships behavior. Are you using HiveLists? If not look into this more closely. Secondly, you may just be trying to save too much when the app is killed. Try changing the save operation before the app is killed to verify proper behavior.

How set and use global variable in flutter app

On main.dart I get response from api username and set `String myUsername = 'stackoverflow';
How on all page use myUsername as global variable?
the answer above is right ,
however if you don't want to make a singleton class,
all you can do is, save it to shared preference, using the
shared_preferences
myPreference.setString("userName", Your user name)
and get it using
myPreference.getString("userName")
You can create a Singleton like this:
class SingletonTest{
String myUsername;
SingletonTest._private();
static SingletonTest _instance = SingletonTest._private();
static SingletonTest get instance => _instance;
}
After that, you can access it from anywhere in your code using:
var singl = SingletonTest.instance;
For more examples refer to:
How to build a Singleton in dart
Or you can use Provider Pattern, more info about it here:
Provider Pattern

Is it possible to use a variable within a variable name?

I have a class for Player that has nextDate, loginDate and saveDate.
Below code works fine and able to retrieve the fields.
DocumentSnapshot documentSnapshot =
await db.collection(Paths.playersPath).doc(uid).get();
Player player = Player.fromFirestore(documentSnapshot);
print('print ${player.nextDate}');
print('print ${player.loginDate}');
print('print ${player.saveDate}');
My question now is if it is possible to use a variable for the nextDate, loginDate and saveDate so that I can just pass which date should I retrieve.
I tried the following but it is not working.
String dateName = 'nextDate';
DocumentSnapshot documentSnapshot =
await db.collection(Paths.playersPath).doc(uid).get();
Player player = Player.fromFirestore(documentSnapshot);
print('print ${player.$dateName}');
Please help. Thanks!
As far as the code snippet is concerned, I can see you have already defined a method fromFirebase to serialize it, in that case you must extract the data payload from the DocumentSnapshot provided by the Firebase DB by using the data method provided by the DocumentSnapshot class. The problem in your case is you're trying to serialize the DocumentSnapshot itself which is not a class of type Map<String, dynamic> which is need for json serialization. If you take a look at the docs, the data method provides a Map<String, dynamic>
Another alternative could be
If you are using FlutterFire plugins that are officially developed by the Firebase and Flutter teams, you can use the withConverter method which can serialize the response for you to the Player class in your case. Here you can find more info about the same.
unluckily, in Flutter mirrors are not available.
You can look it up in the official documentation about this matter.
Nonetheless, the most straightforward workaround is using a Map, so that the keys in that map are your options, and the values the actual property you want to use.
There's a good example in this previous answer.

save data when app closed in flutter provider

https://pub.dev/packages/provider
I used this package for the cart and it works.
But when the app closes, the cart model becomes empty.
What can I do for this problem?
I want to save the previous data when the app is opened.
thanks
you can also use the offline database
for example SQFLITE
Using something like Shared_Prefs sould solve it
it will store your data locally and retrieve them in your providers
create instance
SharedPreferences prefs = await SharedPreferences.getInstance();
set your data
await prefs.setInt('counter', 1);
in your provider retrieve if exist like this
if(prefs.getInt('counter') != null){
someVar = prefs.getInt('counter');
}
you can remove like
prefs.remove('counter');
Note: you can save/retrieve with one of the following types
Only primitive types can be used: int, double, bool, string, and stringList.

storing data so it is globally available in flutter

In my project I am calling the rest API which result gives a list of Map.
my App has 4 bottomtab options, in Dashboard I am hitting the API, and I am doing some operations on the data, but I need the result of that API should be available to all the tabs, else I have to hit again and store in that dart file,
Is there any way whrere I can Hit once and store it into a map and I can use that all over my project?
thanks!
Create a static List variable of your Data by Creating a new Class named Global
class Global
{
static List<MYDataClass> MyDataList = List();
}
to Add Data pass Object of MYDataClass
MyDataList.add(MYDataClass())
to Access it
Global.MyDataList[index].property;
Hope this Help...