I got a setup with a BehaviorSubject. Whenever I load data from an API I call Add to push the data and use it from the stream in a page. Now I want to format some of the data before it is consumed from the stream. As far as I can see Map seems to be the thing to use for a transformation of data, but I'm not sure if it should be set up once or I need to ensure Map is called when data is when data is loaded from an. Currently, I expose a behaviorSubject but if I use map should I then Expose a new stream based on the map?
This is my current setup. From a StreamBuilder in the page I'm using myRides. I can see the applyUnits gets called but its like data is not on the stream anymore
final BehaviorSubject<FeedLoad> ridesSubject = new BehaviorSubject<FeedLoad>();
Observable<FeedLoad> get myRides => ridesSubject.stream.map((item)=> item.applyUnits());
Related
I'm working with Sembast nowadays and was wondering If there's any way to create a stream of data that could get me all the values inside the DB. My requirement is to setup a listener on that stream so that whenever the data change is triggered, I could do something with it.
Documentation on Sembast is pretty limited and I'm now sure how I can do this. Usually I use the .find method to fetch all the values from within my db. I've been using a stringMapFactory to store my records.
Can we do this ? Any help would be really appreciated.
Sorry for the poor documentation.
It is quite similar to firestore. You can listen to all changes in a store
// Track every store changes
var query = store.query();
var subscription = query.onSnapshots(db).listen((snapshots) {
// snapshots always contains the list of all records
// ...
});
Basically you have a query on the store (with or without filter) that you can query or listen for changes.
See https://pub.dev/documentation/sembast/latest/sembast/QueryRef/onSnapshots.html
https://github.com/tekartik/sembast.dart/blob/master/sembast/doc/change_listener.md
If you use Hive as db, may use Hive Box as listenable.
ValueListenableBuilder<Box<YOUR_BOX_MODEL>>(
valueListenable: box.listenable(),
builder: (context,value,child){}
)
Imagine a very simple application with two pages, PostList and PostDetail. On the former page, we show a list of posts, and on the latter, the details of a single post.
Now consider the following scenario. Our user clicks on the first PostItem and navigates to the PostDetail page. We fetch the full post data from the server. The likes_count of this post gets increased by one. Now if our user navigates back to the first page, the PostItem should be updated and show the new likes_count as well.
One possible solution to handle this is to create a pool of posts. Now when we fetch some new data from the server, instead of creating a new post object, we can update our corresponding pool instance object. For example, if we navigate to post with id=3, we can do something like this:
Post oldPost = PostPool.get(3)
oldPost.updateFromJson(servers_new_json_for_post_3)
Since the same object is used on the PostDetail page, our PostItem on the PostList page will be updated as well.
Other approaches that do not use a unique "single instance" of our Post objects, across the application, would not be clean to implement and requires tricks to keep the UI sync.
But the ObjectPool approach also has its own problems and leads to memory leaks since the size of the pool gets bigger and bigger over time. For this problem to get solved we need to manually count the number of references for each pool object instance and discard them when this count is equal to zero. This manual calculation is full of bugs and I was wondering if there are any better ways to achieve this.
You can also solve this by using streams and StreamBuilders. First you create the stream and populates it with the initial data fetched from the API:
I like to use BehaviorSubject from rxdart but you can use normal streams too.
final BehaviorSubject<List<Post>> postsStream = BehaviorSubject<List<Post>>()..startWith(<Post>[]);
On the constructor body or initState function you would fetch the data and add it to the stream.
PostPage() {
_fetchPosts().then((posts) => postsStream.add(posts));
}
You can now subscribe to changes on this postsStream in both pages with StreamBuilder. Any update you need to do you would emit a new (updated) List<Post> to the stream triggering a rebuild on any StreamBuilder subscribed to the stream with the new and updated values.
You can latter dispose the StreamController.
I have been using onSnapshot successfully to alert my code to changes in underlying data, as in
// Set up to listen for changes to the "figures" collection, that is,
// someone has created a new figure that we will want to list on the screen.
setFiguresListener: function () {
// `figuresCR` is a collection reference defined elsewhere
return this.figuresCR.onSnapshot((iFigs) => {
iFigs.forEach((fSnap) => {
const aFigure = figureConverter.fromFirestore(fSnap, null);
const dbid = aFigure.guts.dbid; // ID of the "figure" in the database
nos2.theFigures[dbid] = aFigure; // update the local copy of the data
});
nos2.ui.update();
console.log(` Listener gets ${iFigs.size} figures`);
});
But I now read about on in the docs. It explains:
[The on() function] Listens for data changes at a particular location.
This is the primary way to read data from a Database. Your callback
will be triggered for the initial data and again whenever the data
changes. Use off( )to stop receiving updates. See Retrieve Data on
the Web for more details.
The syntax is a bit different, and on() seems to do much the same as onSnapshot().
So what is the real difference? Should we be using on() instead of onSnapshot()?
on() is an operation for reading from Firebase Realtime Database. That's a completely different database with different APIs than Firestore. They have essentially no overlap. There is no on() operation with Firestore.
If you're working with Firestore, ignore all the documentation about Realtime Database, and stick to using onSnapshot() for getting realtime updates.
Other tyros who fall into this tar pit: in the API doc pages, you might think that since firestore is a database under firebase, you could look for help under firebase.database. But no: look only in the next section, firebase.firestore.
I need a good example of using a service singleton as data source for my Angular 2 application.
Scenario is as following:
I have an application that is loading prices of some items from the local database (in my case MongoDB).
A few of the components need to use a service which will be the universal source of truth for item prices throughout the application. These prices can be acted upon externally: user can change currency, so they have to be recalculated, or can change the date range for which price averages will be calculated.
So I need to have a singleton service which will load upon app initialization and components need to load prices only after the service data store has been initialized with prices. Also, components need to refresh data(I guess using Observable pattern) when, say, the currency or date range has been changed. Perhaps the best way is to inject the service in the app component, so it gets initialized first?
Is there a recipe or proposed architecture for this kind of app?
I can't call some init function from each component with ngOnInit() because I want data available in multiple components. I need to know in each component when to initialize it with data from Service's data store. I need to know when data is ready.
The way I did it in Angular 1.x is to instantiate the service, and in constructor initialize data, and then when the data is initialized, emit a $rootScope event to tell all components that data is ready.
I can't find a proper recipe to do the same thing in Angular 2.
You need to create a service and define it when bootstrapping your application:
bootstrap(App, [ SingletonService ]);
This way you will have a single instance for the whole application.
If you want to initialize things, you can use it constructor. To notify other elements that use the service, you can use one or several properties of EventEmitter. This way you will be able to emit events when data are there or when something changes. Components could subscribe on these EventEmitters to be notify...
We are currently using visjs version 3 to map the dependencies of our custom built workflow engine. This has been WONDERFUL because it helps us to visualize the flow and find invalid or missing dependencies. What we want to do next is simplify the process of building the dependencies using the visjs manipulation feature. The idea would be that we would display a large group of nodes and allow the user to order them correctly. We then want to be able to submit that json structure back to the server for processing.
Would this be possible?
Yes, this is possible.
Vis.js dispatches various events that relate to user interactions with graph (e.g. manipulations, or position changes) for which you can add handlers that modify or store the data on change. If you use DataSets to store nodes and edges in your network, you can always use the DataSets' get() function to retrieve all elements in you handler in JSON format. Then in your handler, just use an ajax request to transmit the JSON to your server to store the entire graph in your DB or by saving the JSON as a file.
The oppposite for loading the graph: simply query the JSON from your server and inject it into the node and edge DataSets' using the set method.
You can also store the networks current options using the network's getOptions method, which returns all applied options as json.