I have a question about hive db. is it possible to store List data type? That's what Hive's documentation says: Generic type parameters like Box are unsupported due to Dart limitations. But i need to store chat with room id and messages.
Lets imagine like that
that is, I need to store 2 different data types into the hive object, List (for message) and int (for id). is it possible? if you have any other ideas please share with me
Thanks
I have solved 🙂 this logic worked for me
final data = ChatStorage(
roomId: widget.room!.id,
chat: state.messages,
);
if (chatBox.isEmpty)
chatBox.put(widget.room!.id, data);
else {
List<int>? roomIds = [];
bool available = false;
for (var chat in chatBox.values) {
roomIds.add(chat.roomId!);
}
if (!roomIds.contains(widget.room!.id)) available = true;
if (available) chatBox.put(widget.room!.id, data);
}
}
I think this method will help if someone is facing such a problem 🙂
Related
Currently, I am working on a Flutter project, which is a tricycle booking system. Right now, I want to implement the functionality of having life points for every account. I have thought of this for some time and I have decided to store a value in the real-time database in firebase, it is where I will be decrementing the life points every time a user cancels the booking. What I want to do right now, is to check if the value stored in lifePoints is equal to a certain value, if yes, then I will be placing some functions and restrictions in there. So, how do i get the data from realtime database using flutter and add conditions to it?
Any help will be much appreciated. Thank you!
If you want to read data from Firebase, the documentation on reading data is a great starting point.
From there comes this great example of reading data once:
final ref = FirebaseDatabase.instance.ref();
final snapshot = await ref.child('users/$userId').get();
if (snapshot.exists) {
print(snapshot.value);
} else {
print('No data available.');
}
And this example for listening for data, which provides both the current value right away, and then continues to listen for updates:
DatabaseReference starCountRef =
FirebaseDatabase.instance.ref('posts/$postId/starCount');
starCountRef.onValue.listen((DatabaseEvent event) {
final data = event.snapshot.value;
updateStarCount(data);
});
If you want to increment/decrement a value in the database, have a look at this example from the documentation on atomic increments/decrements:
void addStar(uid, key) async {
Map<String, Object?> updates = {};
updates["posts/$key/stars/$uid"] = true;
updates["posts/$key/starCount"] = ServerValue.increment(1);
updates["user-posts/$key/stars/$uid"] = true;
updates["user-posts/$key/starCount"] = ServerValue.increment(1);
return FirebaseDatabase.instance.ref().update(updates);
}
Or if you want to perform a more complex update of a value based on its current value, you'll want to use a transaction:
DatabaseReference postRef =
FirebaseDatabase.instance.ref("posts/foo-bar-123");
TransactionResult result = await postRef.runTransaction((Object? post) {
// Ensure a post at the ref exists.
if (post == null) {
return Transaction.abort();
}
Map<String, dynamic> _post = Map<String, dynamic>.from(post as Map);
if (_post["stars"] is Map && _post["stars"][uid] != null) {
_post["starCount"] = (_post["starCount"] ?? 1) - 1;
_post["stars"][uid] = null;
} else {
_post["starCount"] = (_post["starCount"] ?? 0) + 1;
if (!_post.containsKey("stars")) {
_post["stars"] = {};
}
_post["stars"][uid] = true;
}
// Return the new data.
return Transaction.success(_post);
});
As you might notice these are all code snippets from the documentation, all from the same page even. I recommend spending some time studying that documentation, and then trying to apply these to your own use-case. If you then run into problems while implementing the use-case, post a question with the minimal code that reproduces where you got stuck and we can probably help further.
I am struggling to reference specific things in my firebase real time database. I understand that when you want to read something specific from the database you need to specify the exact path where the item can be found.
If you see the screenshot attached, I want a way to read the name of each menuItem and store them in a list.
It seems like this can only be done if you reference each menuItem ID individually in the path (like in the code below).
Is there not a way to say ("menuItem/itemID/itemName") so that I can access each menuItem name dynamically using a for loop with a terminating value equal to the number of menu items in the database?
Any help would be greatly appreciated!
final DatabaseReference _dbRef = FirebaseDatabase.instance.ref();
late DataSnapshot _itemStream;[![enter image description here][1]][1]
Future<List<String>> _readItemNames() async {
_itemStream = await _dbRef.child("menuItem/J1/itemName").get();
itemName = _itemStream.value.toString();
itemNames.addAll([itemName]);
_itemStream = await _dbRef.child("menuItem/J2/itemName").get();
itemName = _itemStream.value.toString();
itemNames.addAll([itemName]);
return itemNames;
}
If you want to read and process all menu items, you can do:
var snapshot = await _dbRef.child("menuItem").get();
snapshot.children.forEach((childSnapshot) {
var props = childSnapshot.val() as Map;
print(props["itemName"]);
});
For more on this, see the Firebase documentation on reading a list of items with a value event (you're just using get() instead of onValue, but the logic is the same).
There is no way to get only the itemName property of each child node, so if all you need it the names you're loading more data than needed. If that is a concern, consider creating an additional list with just the value(s) you need. For example:
menuItemNames: {
"J1": "Milk Shake",
"J10": "Name of J10",
...
}
I am trying to get the most recent ID of from my orders table to that I can then use this ID in a path to get the order number and increment it by one.
void _activateListeners() {
final recentOrder = _readRef.child('Orders').limitToLast(1).get();
final readOrder = _readRef
.child('Orders/{$recentOrder}/orderNum')
.onValue
.listen((event) {
final orderNum = event.snapshot.value;
setState(() {
lastOrderNum = orderNum.toString();
intOrderNum = int.parse(lastOrderNum) + 1;
newOrderNum = intOrderNum.toString();
});
});
}
I know that I need to use the "key" word somehow but I have been unable to solve this problem.
my database table looks as follows:
Orders
-N3ZdY6LOL_9Z-6KXHnK
*cartProduct
*dateTime:"2022-06-02 15:41:20.470139"
*orderNum:"6"
*totalAmount:45
-N3ZdgEQIzsjLA5NCu3U
*cartProduct
*dateTime:"2022-06-02 15:41:20.470139"
*orderNum:"7"
*totalAmount:45
Edit: can someone tell me if it is even possible to fetch the unique push ID after it has been made (not directly after the order is added)? I have looked at all the documentation and I have failed to implement anything. I have also found numerous similar questions that are either just different or unanswered.
If I know SQL is SQLite a better alternative?
You can get the key from the snapshot by using the snapshot's key property, like in this line below:
String? eventKey = event.snapshot.key;
Check out the documentation for Flutter's Realtime Database's DataSnapshot class for more information.
i All,
The Project: A handy utility for tickets at work to help sort and manage my tickets, built on top of our provider's API.
My Background: I'm like 19 hours total into dart and am almost done with my first bootcamp.
The GIST: I have started writing a provider for our helpdesk software's API. I am sending requests to the API successfully but I am utterly clueless on transforming the data into an actual map to generate ticket instances with.
What I'm trying to accomplish:
Fetch the data from the API
Convert that String into a MAP of json objects that I can iterate
through
Iterate through the JSON objects to create instances of ticket
objects with
build a list of those ticket objects and return it to requestor to
generate a widget list.
I could swear I've done everything reasonable to try and type cast this as a map but I think there is something I just don't understand. FWIW I think whatever it is I'm trying to do is accessing a Future not the actual data. and I think i might be confused or unclear about async/awaits but my understanding of the code I've written is that the actions are chained one to another so I shouldn't be "waiting" for anything or getting a future, I should just be getting a string.
Otherwise, Here's my code cleaned up, any advice or suggestions on working with the data in the print would be much appreciated.
class ticketingsoftwareAPIProvider {
// Object Properties
Client _client = Client();
final String _ApiKey = "YOUSHALLPASS!";
final String apiRoot = "https://api.ticketingsoftware.com";
final String agentId = '2675309';
getAgentTickets() async {
// Headers for our HTTP Request
Map<String, String> headers = {
'X-ticketingsoftware-Authorization': 'Bearer $_ApiKey',
'Accept': 'application/vnd.ticketingsoftware.v2.1+json',
'Content-Type': 'application/json'
};
await _client
.get(Uri.parse('$apiRoot/incidents.json?assigned_to=$agentId'))
.then((data) {
if (data.statusCode == 200) {
print(json.decode(data.body));
// CANT SEEM TO MAKE THIS A INTO A MAP TO GENERATE OBJECTS WITH.
}
});
}
}
} // END CLASS
I apologize for any missing information, I am new to dart and REALLY programming in general and am still learning the culture. please let me know if there is any additional information that might help.
My Solution ended up being:
List ticketJson = json.decode(data.body);
for (var ticket = 0; ticket < ticketJson.length; ticket++) {
thisAgentsTickets.add(incident.fromJson(ticketJson[ticket]));
return thisAgentsTickets;
I think I've been learning from a very out of date course.
You need fromJson method to convert it to an object. For example
if (data.statusCode == 200) {
return AgentTicket = AgentTicket.fromJson(data.body)
}
Use json_serializable package for easy way to create the method, or you can create it manually too.
sorry I am new in using Flutter and using Hive local storage.
I am using
hive: ^2.0.4
hive_flutter: ^1.0.0
I open the box in main function like this
Future<void> main() async {
await Hive.initFlutter();
await Hive.openBox<List<Event>>("events");
}
after getting the data from the server, I save all the events to hive by using code like this
final eventsBox = Hive.box<List<Event>>("events");
final List<Event> eventsFromServer = await getEventsFromServer();
eventsBox.put("recommended_events", eventsFromServer);
but I have error when trying to read the data from the box, I read it like this
final eventsBox = Hive.box<List<Event>>("events");
// error in this one line below
final eventsFromHive = eventsBox.get("recommended_events", defaultValue: []) ?? [];
type 'List < dynamic > ' is not a subtype of type 'List< Event >?' in type
cast
how to solve this type casting error?
from the documentation in here it is said
Lists returned by get() are always of type List (Maps of type
Map<dynamic, dynamic>). Use list.cast() to cast them to a
specific type.
I don't know if it is the solution of my problem or not, but I don't know how to implement that in my code.
I tried it like this, but I still have the same error
final eventsFromHive = eventsBox.get("recommended_events")!.cast<Event>();
or maybe the way I write the syntax to save and read the list are totally wrong? please help :)
Is not necessary to open your box as a List, because it is a box and can store many objects of the type that you declare, for example:
await Hive.openBox<MyModel>(boxName);
To get all the objects or data stored in that box, you can query like this:
final box = Hive.box<CompanyModel>(boxName);
List<CompanyModel> interviews = box.values.toList();
In addition, you have to create an Adapter Model if you want to store your own Model with Hive.
There is two dev dependencies to auto generate the Model:
dev_dependencies:
hive_generator:
build_runner:
Importing that dependencies and running this command flutter packages pub run build_runner build will generate the Model, but also you have to create your Model as the documentation indicates.
I suggest you to check out the documentation.
Hive - Generate Adapter
I can finally solve it by using it like this. in main function
Future<void> main() async {
await Hive.initFlutter();
await Hive.openBox("events");
}
when saving data list
final eventsBox = Hive.box("events");
eventsBox.put("recommended_events", eventsFromServer);
and read it like this
final eventsBox = Hive.box("events");
final eventsFromHive = eventsBox.get("recommended_events")?.cast<Event>() ?? [];
I have faced this kind of problem. It was absolutely the same. I do not know how you got kinda problem. Maybe it was the same with mine. I have just cleaned the box. and it has worked on me.
**Cause: **
I started it immediately after I made the box (for testing). he had taken the List<dynamic> object as it store. Once I made it clear, it stocked up data I had just given and it worked
Try:
boxName.clear() inside initState() and re-run it. if it will work do not forget to delete the line!
if you forget, it will clear the box every time.
Done with getting Hive as an List Object :)
Future<List<CustomModel>> getModels() async {
//box = await Hive.openBox<CustomModel>(Constants.Hive);
return box?.values.toList(growable: false)?.cast<CustomModel>() ?? <CustomModel>[];
}