How to reference the same object that comes from diferents streams? - flutter

I have an application with an api works like a web (when you ask for 'favorites' it sends a json with some elements that fit in the category, when you ask for all the elements it sends another list, which contains the favorites as well, but when the json is transformed it will be a reference of a different object).
I am trying to find the best way, not to make a call each time, storing the view in a tab and working with 'streams' instead of 'builders', but how to update the object if in a category view we assign a value to it, and when we go back to the full list tab (without reloading), show the change in the object that represents the same one that we have in favorites?
Actually I am storing the first reference of the object in a block, in an array of objects, if we first call 'favorites' the next time the same object arrives from another source, it references the first occurrence of the same object, it works, but the object list can be very large and I'm afraid maybe not the best implementation.
In a prefect world I would like not to have to store the objects and just work with the tabs loaded in streams, but I don't know how to propagate the change if the same item is on different tabs.
Any idea for a good implementation?

Related

Does the Javascript Firestore client cache document references?

Just in case I'm trying to solve the XY problem here, here's some context (domain is a role-playing game companion app). I have a document (campaign), which has a collection (characters), and I'm working with angular.io / angularfire.
The core problem here is that if I query the collection of characters on a campaign, I get back Observable<Character[]>. I can use that in an *ngFor let character of characters | async just fine, but this ends up being a little messy downstream - I really want to do something like have the attributes block as a standalone component (<character-attributes [character]="character">) and so on.
This ends up meaning down in the actual display components, I have a mixture of items that change via ngOnChanges (stuff that comes from the character) and items that are observable (things injected by global services like the User playing a particular Character).
I have a couple options for making this cleaner (the zeroth being: just ignore it).
One: I could flatten all the possible dependencies into scalars instead of observables (probably by treating things like the attributes as a real only-view component and injecting more data as a direct input - <character-attributes [character]="" [player]="" [gm]=""> etc. Displayable changes kind of take care of themselves.
Two: I could find some magical way to convert an Observable<Character[]> into an Observable<Observable<Character>[]> which is kind of what I want, and then pass the Character observable down into the various character display blocks (there's a few different display options, depending on whether you're a player (so you want much more details of your character, and small info on everything else) or a GM (so you want intermediate details on everything that can expand into details anywhere).
Three: Instead of passing a whole Character into my component, I could pass character.id and have child components construct an observable for it in ngOnInit. (or maybe switchMap in ngOnChanges, it's unclear if the angular runtime will reuse actual components for different items by changing out the arguments, but that's a different stack overflow question). In this case, I'd be doing multiple reads of the same document - once in a query to get all characters, and once in each view component that is given the characterId and needs to fetch an observable of the character in question.
So the question is: if I do firestore.collection('/foo/1/bars').valueChanges() and later do firestore.doc('/foo/1/bars/1').valueChanges() in three different locations in the code, does that call four firestore reads (for billing purposes), one read, or two (one for the query and one for the doc)?
I dug into the firebase javascript sdk, and it looks like it's possible that the eventmanager handles multiple queries for the same item by just maintaining an array of listeners, but I quite frankly am not confident in my code archaeology here yet.
There's probably an option four here somewhere too. I might be over-engineering this, but this particular toy project is primarily so I can wrestle with best-practices in firestore, so I want to figure out what the right approach is.
I looked at the code linked from the SDK and it might be the library is smart enough to optimize multiple observers of the same document to just read the document once. However this is an implementation detail that is dangerous to rely on, as it could change without notice because it's not part of the public API.
On one hand, if you have the danger above in mind and are still willing to investigate, then you may create some test program to discover how things work as of today, either by checking the reads usage from the Console UI or by temporarily modifying the SDK source adding some logging to help you understand what's happening under the hood.
On the other hand, I believe part of the question arises from a application state management perspective. In fact, both listening to the collection or listening to each individual document will notify the same changes to the app, IMO what differs here is how data will flow across the components and how these changes will be managed. In that aspect I would chose whatever approach feels better codewise.
Hope this helps somewhat.

REST Route/Input Design

I have one Restaurant to many Menu, one Menu to many Category, one Category to many Item. I'm stuck trying to find the best way to lay out the routes for these models. Here are the options I see:
I can flatten the routes and simply require the id of the parent model.
this makes the routes simple, but requires an extra input/parameter every time I want to do anything with the model.
GET /menus?restaurant_id=X
POST /menus?restaurant_id=X&name=foo&description=bar
I can nest all the routes within their given parent models.
this makes the routes long, but doesn't require any extra inputs/parameters
this adds unnecessary information to certain lower-level models (don't need to know restaurant directly when accessing categories/items)
GET /restaurant/:restaurant_id/menus
POST /restaurant/:restaurant_id/menus?name=foo&description=bar
GET /restaurant/:restaurant_id/menus/:menu_id/categories/:category_id/items
Is there a good standard for which to choose?
I would go with your very last example - I try to keep URL params to a minimum for readability and cache/proxy concerns.
I would design it as such:
menus
POST /menus?restaurant_id=123&name=foo&description=bar
GET /menus?id=890 // specific menu
GET /menus?/restaurant_id=123 // many menus
Items
POST /items?category_id=594&name=milkshake&description=vanilla
more generically
POST /<model_of_interest>?<parent_of_model_of_interest>&<other>&<parameters>
GET /<model_of_interest>?<model_of_interest_id>
As you can see this would work for your top most and bottom most model without any additional cruft. Then validate the request and enforce access with your models which should be easily abstracted given the "only one parent" scheme you are going for (i.e. by passing &category_id=345 to create item route, you can easily construct the rest of your object and know for certain that 345 can only ever belong to menu_id=123 which can only even belong to restaurant_id=...).
This has the benefits of :
not providing information the parent models already have
allowing specific selection of a singular object "downwards" (e.g. give me item where id=338)
allowing universal selection downwards (e.g. give me all items where category_id=123)

WinRT ISupportIncrementalLoading View with Both Directions

I've a ItemsControl which shows a list of days with some data.
I want this control so be able to scroll infinitely in two directions.
With ISupportIncrementalLoading I could add more days when the end is reached.
But how can I achieve this when the first element is reached?
Does somebody now a collection class which returns the postion of the currently first displayed item?
Any hints?
One possibility is IObserveableVector, per this page on MSDN: Load, store, and display large sets of data efficiently
IObserveableVector allows you to access data in a random access order, which would allow you to load data at both ends of the list.
I have not used it, nor have I seen many examples on how to use it.

How to check for existing item in NSSet or NSCountedSet?

I'm currently populating model objects into an NSSet (perhaps I should be using NSCountedSet). The models should be unique. What I do is pull them in from a web service, and then instantiate them on the client-side and add them to a set.
My problem is the following: There are times when I'll only pull one model and add it to the set, for instance say I have an inventory of Ferrari's. So I'll ask my server to pull me in one specific Ferrari because an individual clicks on that Ferrari's detail view from an inventory. The individual Ferrari detail view will list all of the different paints available for this model. So once the user drills into this Ferrari view, I will ask the server for all of the paints available for a particular Ferrari model.
Next, the user backs out and then goes to a view controller which asks for all of the paint colors I have available for every vehicle. I already have the Ferrari paints available in a stash. Now I'm asking for ALL of the paints from the server. What's the best way to aggregate the existing paints with all of the paints without duplicating resources?
What you need is a way to uniquely identify each object from the server. In a database an object (part or whole) can be represented as a row and the rowid is typically a monotonically increasing integer (although your data source could use something else). In any case, store this unique id in each object you create, and before creating a new object check for the existence of an object with that id. If the object already exists, return the existing object, and if it doesn't, create a new object and then store it in the cache. Using integers as ids works out nicely, because you can use NSMapTable as a cache with the rowids as the keys, and the values are the object pointers.
Maintain an NSArray* in your app which stores NSString* objects based on some hash function of your features:
hashValue = hash(color + horsepower + leatherSeating + whatever...)
For example, you might take the SHA1 hash of a collated string (example code).
Take the features you obtain from the web service and generate a hashed value from them using the same function.
Search your app's hash table for the web-service-value using -containsObject:.
If it returns YES, do X, else do Y.

What is the most practical Solution to Data Management using SQLite on the iPhone?

I'm developing an iPhone application and am new to Objective-C as well as SQLite. That being said, I have been struggling w/ designing a practical data management solution that is worthy of existing. Any help would be greatly appreciated.
Here's the deal:
The majority of the data my application interacts with is stored in five tables in the local SQLite database. Each table has a corresponding Class which handles initialization, hydration, dehydration, deletion, etc. for each object/row in the corresponding table. Whenever the application loads, it populates five NSMutableArrays (one for each type of object). In addition to a Primary Key, each object instance always has an ID attribute available, regardless of hydration state. In most cases it is a UUID which I can then easily reference.
Before a few days ago, I would simply access the objects via these arrays by tracking down their UUID. I would then proceed to hydrate/dehydrate them as I needed. However, some of the objects I have also maintain their own arrays which reference other object's UUIDs. In the event that I must track down one of these "child" objects via it's UUID, it becomes a bit more difficult.
In order to avoid having to enumerate through one of the previously mentioned arrays to find a "parent" object's UUID, and then proceed to find the "child's" UUID, I added a DataController w/ a singleton instance to simplify the process.
I had hoped that the DataController could provide a single access point to the local database and make things easier, but I'm not so certain that is the case. Basically, what I did is create multiple NSMutableDicationaries. Whenever the DataController is initialized, it enumerates through each of the previously mentioned NSMutableArrays maintained in the Application Delegate and creates a key/value pair in the corresponding dictionary, using the given object as the value and it's UUID as the key.
The DataController then exposes procedures that allow a client to call in w/ a desired object's UUID to retrieve a reference to the actual object. Whenever their is a request for an object, the DataController automatically hydrates the object in question and then returns it. I did this because I wanted to take control of hydration out of the client's hands to prevent dehydrating an object being referenced multiple times.
I realize that in most cases I could just make a mutable copy of the object and then if necessary replace the original object down the road, but I wanted to avoid that scenario if at all possible. I therefore added an additional dictionary to monitor what objects are hydrated at any given time using the object's UUID as the key and a fluctuating count representing the number of hydrations w/out an offset dehydration. My goal w/ this approach was to have the DataController automatically dehydrate any object once it's "hydration retainment count" hit zero, but this could easily lead to significant memory leaks as it currently relies on the caller to later call a procedure that decreases the hydration retainment count of the object. There are obviously many cases when this is just not obvious or maybe not even easily accomplished, and if only one calling object fails to do so properly I encounter the exact opposite scenario I was trying to prevent in the first place. Ironic, huh?
Anyway, I'm thinking that if I proceed w/ this approach that it will just end badly. I'm tempted to go back to the original plan but doing so makes me want to cringe and I'm sure there is a more elegant solution floating around out there. As I said before, any advice would be greatly appreciated. Thanks in advance.
I'd also be aware (as I'm sure you are) that CoreData is just around the corner, and make sure you make the right choice for the future.
Have you considered implementing this via the NSCoder interface? Not sure that it wouldn't be more trouble than it's worth, but if what you want is to extract all the data out into an in-memory object graph, and save it back later, that might be appropriate. If you're actually using SQL queries to limit the amount of in-memory data, then obviously, this wouldn't be the way to do it.
I decided to go w/ Core Data after all.