Hey allI am trying to achieve the following behavior:
There are two Objects.
Y(bool saved, int id) and X(Y y, bool liked, int id)
Three views ViewA, ViewB, and ViewC can be accessed from a BottomNavBar. So all of them will be loaded during app usage. Views A and B will display a list of X and View C will display a list of Y. Even though A and B will show different lists, some items might be the same. Also, some of the nested Y's in the X's might be displayed on ViewC as well.
Items being the same requires me to synchronize all of the lists in some way. I have been thinking about this but so far could not come up with an efficient solution.
My current implementation is as follows:
xRepo has a Map<int, BehaviorSubject> allX that will keep a map of streamcontrollers that my xBloc will subscribe to. the integer here is the id of the X or Y objects. The same goes for yRepo and a streamcontroller to be subscribed by yBlocs.
I also have a single ListBloc which takes care of fetching the lists of X and Y, and asking the repo to update each fetched item by the newly fetched one. Upon fetching a list of Xs, I update both the allX and allY streamcontrollers (because the fetch of X might include up to date information about the Y objects) I use a ListView that builds a list of xCards and yCards in the corresponding views. I use xBloc and yBloc provided to each xCard and yCard to subscribe to the streamcontroller that is mapped with the id of the item allX and allY streamcontrollers. This way, an update in the saved value of Ys and liked value of Xs will be reflected to all of the UIs at the same time.
This implementation causes my app to be clanky because the Bloc provided to each card subscribes to the corresponding streamcontroller in allX or allY. And I think scrolling these cards up and down hurts the rendering in some way.
I need a better, more efficient implementation. Sorry the way I described the problem was too complicated. The problem is a rather complicated one for me.
Related
I am building a text-based adventure game as follows: I have 2 models Node and Message, in Node will contain:
1 list of messages
1 list of branching conditions
1 list of child nodes
My idea is to use Listview to print to the screen and when the user interacts with the conditions the data in that listview will be updated accordingly.
The problem I have here is that if I use If - else it will take a long time to process all the cases if the plot is long. And the nodes are nested in a tree model, so it's quite complicated.
Let me know the best solution to implement it.
Thank you!
For the presentation I would not care about any if else statement.
I would completely separate the story logic from the presentation.
Thus, you could have a field in your UI which is always holds the latest message and you could always show that to the UI. Or a list of all previous messages and you always show the last element of the list.
Additionally, I would write a story manager class which handles the different routings of the story tree and updates the field in your UI which holds the latest message.
There's no need to use any if-else if your condition points to the specific id of the next message and next conditions from two big lists with all messages and all conditions.
So, my humble solution is to have a list of all Messages and a list of all Conditions. Each Message has an id, and each Condition has an id. So the click on condition will invoke loading of the specific Message.id and several Condition.id. Condition model looking like:
class Condition {
final String id;
final String nextMessage; // here will be an id of the next message to display
final List<String> nextConditions; // and then you display next conditions
So in reality each condition will look like:
Condition(id: 'A1', nextMessage: 'B', nextConditions: ['B1','B2','B3']);
The architecture management of lists you can always improve and maybe come up with some clever ids so it is easier to understand which lead to which.
I'm writing a Flutter web/mobile calendar application / todo list, the main feature of which is a long list of items (appointments, tasks, and the like).
Much of the time, the list won't be longer than a few hundred items. But it should be able to scale to thousands of items, as many as the user wants. Not too hard to do should the user make many repeating items. I'm using ReorderableListView.builder to virtualize the list. The part I'm struggling with is when to load the list data and how to store it.
Important: When the user picks a day, the list can jump to somewhere in the middle... and can scroll back to the top of the list.
The easiest thing to do would be to just load all data up to the users position. But this means storing a potentially very large list in memory at best, and in the web application it means requesting way more data than is really needed.
A good summary of the problem might be: Jumping to particular day is more challenging than jumping to a known index on the list. It's not easy to know what an item's index would be in a fully constructed version of the list without fully constructing the list up to that item. Yes, you can get items at particular date, but what if you wanted to get fifty items before a particular date, and fifty items after a particular date (useful for keeping scrolling smooth)? There could be a huge gap, or there could be a whole ton of items all clustered on one day.
A complication is that not all items in the list are items in the database, for example day headers. The day headers need to behave like regular items and not be attached to other items when it comes to the reordering drag animation, yet storing them as records in the database feels wrong. Here's an image of the web application to give you some idea:
THIS ANSWER IS MY OWN WORK IN PROGRESS. OPEN TO BETTER ANSWERS, CORRECTIONS.
I like the answer here (Flutter: Display content from paginated API with dynamic ListView) and would like to do something like it.
I would do this both for web app, where there's http bottlenecks. I would also do this for the mobile app, even when all data is in the database. Why keep the entire list in memory when you don't have to? (I have very little mobile development experience, so please correct me if I'm wrong)
Problem:
Jumping to particular day is more challenging than jumping to known index on the list. It's not easy to know what an item's index would be in a fully constructed version of the list without fully constructing the list up to that item.
Solution I'm leaning toward:
ReferencesList + keyValueStorage solution
Store the item ids in order as well as key value pairs of all items by id as a json list in NoSql. This list will include references to items, with day headings included and represented by something like 'dh-2021-05-21' or its epoch time. This list will be very lightweight, just a string per item, so you don't need to worry about holding it all in memory. Item data can be pulled out of storage whenever it's built. (Should this be a problem in Sembast or hive? Hive, and here's why: https://bendelonlee.medium.com/hive-or-sembast-for-nosql-storage-in-flutter-web-fe3711146a0 )
When a date is jumped to, run a binary search on this list to find its exact position and scroll to that position. You can easily preload, say 30 items before and 50 items after that position.
other solutions:
SplayTreeMap + QuerySQLByDate Solution:
When jumping, since you don't know the index, insert it into a new SplayTreeMap at an arbitrarily high index, say 100 * number_of_list_items_in_database just to be safe. Run two queries, on ascending from scrolled to date, and one descending from it. Cache these queries and return them in paged form. Should the user reach the beginning of the list, simply prevent them from scrolling further up the list manually with a ScrollController or something like it.
When using Flutter with realtime databases, such as Firebase Database, it is beneficial to know not just that a collection has been updated, but where exactly. Such as to show a pretty list animation, or trigger some additional events based on which item has updated. Dart already has an amazing infrastructure for delivering events.
A canonical example is to use a FirebaseAnimatedList, but it's glued to Firebase and doesn't support filtering and ordering (outside of very basic Firebase model). I am looking for a more generic solution, which would allow to inject some logic between database (that notifies of item change/insert/delete), and aforementioned AnimatedList, which expects the same events.
Most recent tendency seems to be in favor of immutable collections, such as built_value, which makes a lot of sense in Dart, as object creation is very cheap. However, immutable collections do not have a way of telling which item has changed, they simply deliver a new collection. This approach also makes it difficult to attach some local information to an item, such as "selected" bit when user multi-selects items, or custom ordering. Because, well, items are immutable, and their reference (aka pointer, aka object ID) keeps changing.
One alternative solution is to implement a kind of observable list, such as what package:observable offers, but it seems that its authors are not convinced of its popularity anymore. So what is the approach you take to create animated, filtered, sorted, selection-supporting lists in Flutter, backed by a realtime database?
However, immutable collections do not have a way of telling which item has changed, they simply deliver a new collection.
Some pseudo code: (old collection) - (new collection) = (what changed) - works the other way around too.
This approach also makes it difficult to attach some local information to an item, such as "selected" bit when user multi-selects items, or custom ordering.
Extend said 'item' and add a property selected (or order, or any other info you want available), then just construct the new list with these properties properly set.
There are a lot of state-management-with-Flutter-related questions around these days, so to avoid repeating myself, I would rather link you to an answer of mine from earlier today.
Edit:
I just want to insert a practical example regarding (old collection) - (new collection) = (what changed):
Basically this is how to see what changed when comparing 2 lists, containing closely related elements.
List currentState = [...];
List nextState = [...];
List addedItems = nextState.where((e) => !currentState.contains(e)).toList(),
List removedItems = currentState.where((e) => !nextState.contains(e)).toList();
doSomethingWith(addedItems);
doSomethingElseWith(removedItems);
Of course you should keep in mind that the Lists should be deeply comparable, i.e. for Dart's specific case you can use built_value or equatable packages.
I have also uploaded a repository, with a pure Dart project example. You're more than welcome to do whatever you want with the code.
I'm right now experimenting with a nodejs based experimental app, where I will be putting in a list of books and it will be posted on a forum automatically every x minutes.
Now my question is about order of these things posted.
I use mongodb (not sure if this changes the question or not) and I just add a new entry for every item to be posted. Normally, things are posted in the exact order I add them.
However, for the web interface of this experimental thing, I made a re-ordering interaction where I can simply drag and drop elements to reorder them.
My question is: how can I reflect this change to the database?
Or more in general terms, how can I order stuff in general, in databases?
For instance if I drag the 1000th item to 1st order, everything below needs to be edited (in db) between 1 and 1000 the entries. This does not seem like a valid and proper solution to me.
Any enlightenment is appreciated.
An elegant way might be lexicographic sorting. Introduce a String attribute for each item. Make the initial length of the values large enough to accomodate the estimated number of items. E.g., if you expect 1000 items, let the keys be baa, bab, bac, ... bba, bbb, bbc, ...
Then, when an item is moved from where it is to another place between two items, assign a value to the sorting attribute of the moved item that is somewhere equidistant (lexicographically) to those items. So to move an item between dei and dej, give it the value deim. To move an item between fadd and fado, give it the value fadi.
Keys starting with a were initially not used to leave space for elements that get dragged before the first one. Never use the key a, as it will be impossible to move an element before this one.
Of course, the characters used may vary according to the sort order provided by the database.
This solution should work fine as long as elements are not reordered extremely frequently. In a worst case scenario, this may lead to longer and longer attribute values. But if the movements are somewhat equally distributed, the length of values should stay reasonable.
I have a Triangle class. Each Triangle has three edges a, b, and c, and also three angles angleA, angleB, and angleC. In addition to the size (length or angle), each datum also stores whether it was entered by the user or was calculated based on geometric relationships to other data.
Corresponding to my Triangle class, I have a TriangleSidesAndAnglesView. This view has six subviews -- one for each of the angles, and one for each of the sides. The contents of the subviews depends on the information in the model class. The subviews are all of class TriangleDatumView.
Information can pass both ways. For example, if the user enters something in a text field corresponding to an edge or angle, the entered value needs to be passed up to the model.
I am trying to figure out how to keep everything organized. For example, should the TriangleDatumView objects contain references to the respective corresponding members in the model class? Does the TriangleSidesAndAnglesView need to keep a table of which TriangleDatumView corresponds to what model object? Should the TriangleDatumView for (say) edge b know that the name of the edge it is displaying is "b" so that it can write "b=" each time . . . or does it grab that info from the model?
Nothing here is fundamentally difficult. The challenge is organizing it all in a sensible way.
Thanks for any help.
A question I ask myself is "What do I want to be able to independently vary?" -- meaning, if I have a model, could I imagine a totally different implementation of the same interface or a totally different view for the same model. In the variations that I care about, what needs to be where.
So, if labels are always A, B, and C -- I see no reason to store labels in the model. If they can change, then yes, you should not hard-code them in the view.
Views in MVC often have references right to the model they are viewing. Sometimes the controller is an intermediary. Models should usually not contain references to views -- but instead use things like delegates to alert of changes to their state.
I'm in the "Do the simplest thing that works, and don't repeat yourself, refactor when necessary" camp. The issue with building in the complexity at the start is that it might be complex on the wrong axis -- let the features dictate how the interfaces grow.
A view controller could sit between model and view, managing an array of TriangleView instances. The controller adds, modifies and deletes views based on what is in the model, and does the same for model instances based upon changes to the parent view (typing in a text field, tapping and dragging, and other UI actions, etc.).