Lazy loading data after initial load - sapui5

In section 10 of the OpenUI5 Developer Guide tutorial on routing (see here), it talks about lazy loading. However the tutorial does not show how to lazy-load data.
Scenario: I have an OpenUI5 app that gives a list of employees and on a detail page shows the main employee details and gives access to further info, projects, hobbies, and notes from the selected employee's resume.
Because in 99.99% of the use cases a user will not wish to look at hobbies, I will prefer not to load hobbie data with the main model for the app. I make this choice based on performance concerns. Instead I will detect the user has requested to see hobbies and load the hobbies data for the current user into the model.
How would I do that ?
Edit: I managed to discover the onTabSelect() plumbing [tip to other confused folks, the OpenUI5 tutorials tend to leave stuff out to keep on topic - it is useful to look at the code of their working versions if you get lost]. After this the routing in the tutorial makes a lot more sense.
My question remains relevant but changes slightly to 'User clicks a tab and I am about to load further JSON data into the model. Should I do this in onInit() of the target controller or before navTo() is invoked to load the controller?' I can see an issue because of the async nature of the JSON fetch meaning if I use onInit() I could end up displaying the page controls before the data arrives.
What is the best practice please ? My money is on pre navTo() though that is an ugly pattern as I would have to repeat the JSON fetch elsewhere if I have another route to the lazy-loading view.

To stick with the example. You can attach your HobbiesController in its onInit method to the display event of the target you are displaying:
var router = this.getOwnerComponent().getRouter();
var target = router.getTarget("resumeTabHobbies");
target.attachDisplay(this.onDisplay, this);
Then you define an onDisplay method which will be now called if you select the corresponding tab and populate your model there.

Related

Flutter - multi cubit/bloc architectural design pattern

What's the best approach to make something like parent-children bloc architecture? Very often I face a problem when there is a need to establish communication between cubits or blocs.
Let's image a form where we would like to create a new user:
User name
User role (separate cubit, fetch all possible option from API)
Calendar (separate cubit, a lot of calculations made)
Apply button (main BLoC which is responsible to save new user). First
approach:
We need to get each cubit's state and emit new state when clicking on Apply button.
First approach:
var role = context.read<RolesCubit>().state as RoleSelected;
var date = context.read<CalendarCubit>().state as DateSelected;
context.read<CreateUserBloc>.add(CreateNewUserEvent((role: role, date: date));
Pros:
good granulation,
each small cubit is responsible for one thing eg getting a list of available roles and choose one
easier to maintain tests,
cubits can be reused in many places
Cons:
a need to remember to update in each place where main CreateNewUserEvent is added (imagine we would like to add 3rd sub cubit responsible for Access or Salary).
need to know each sub-cubit's state before we add "main" event. I should copy this logic to other places where this event is added. Maybe another example: I wanted to follow this approach with paginated list, on scroll refresh indicator action and one of sub page, therefore I had to check each sub-cubit state and after that I could add main event CreateNewUserEvent;
Second approach:
context.read<CreateUserBloc>.add(DateChanged((newDate));
context.read<CreateUserBloc>.add(RoleChanged((newRole));
context.read<CreateUserBloc>.add(CreateNewUserEvent(());
Create one big BLoC which can do all responsibilities.
Pros:
everything is kept in one place. When we select new role or new date,
"master" BLoC is immediately informed about change and decides what
to do next.
Cons:
big piece of code which is hard do maintain and test smaller parts
can not be reused in other places because it's monolith
Third approach
Stream subscription and make "master" bloc strictly dependent of sub-cubits. Master's cubit constructor requires a stream of sub-cubits. Explained here:
I hope I explained a problem in a simple way. Whats the best approach to maintain complex architectural design in flutter?

How to improve performance on mobile devices using xamarin forms

We are using xamarin forms with prism. We have simple pages with small amount of data to be displayed on each page and include simple calculations. We are using prism navigation service to navigate between pages. We are experiencing some latency from clicking a button to navigating to next page. Data is fetched inside OnNavigatedTo since navigation parameter changes the data. Can someone shed some light of why is there a latency, it is close 1+ second and sometimes 2 seconds.
Also, it seems like each page is getting rendered twice... Once before OnNaviagatedTo and then data changes. OnProperty or OnCollection changed is fired from within OnNavigatedTo and it seems to cause the rendering again.
Version 6.3.0 introduced the concept of OnNavigatingTo, while OnNavigatedTo has been around for a while. There is a distinct difference between the two. Understanding the order in which things occur should help you create a nicer user experience.
New Page is created
OnNavigatedFrom is called
OnNavigatingTo is called
New Page is pushed onto the Navigation Stack and becomes visible
OnNavigatedTo is called
Applications that have to reach out and fetch data can often experience latency issues because it takes time to reach out to the remote service and get the data we want and then parse that data into a usable object. This particular problem was one in which many developers wanted to cut down the demand on the UI with having to refresh as the bindings were being updated which led to the introduction of OnNavigatingTo.
While neither one will reduce network latency it gives you an ability to make the calling page enter an IsBusy state that may display some sort of loading icon which would then be updated to false when NavigateAsync completes and your new page is displayed already loaded.

mvvmcross editting a complex object over multiple pages and saving data

I'm fairly new to mvvmcross and the mvvm model in general. I have been trying to create my own cross platform app for several weeks now and I'm stuck at what would be good practice. I have two main problems, I hope somebody can help me with
Question 1:
I have a complex model with many properties, sub items, and sub items in those sub items. Also, many values are automatically calculated based on other values.
I implemented the MvxNavigatingObject everywhere, and all values are correctly notified when changes occured. So far so good.
Now I want to let people use the app to change the values in my model. But because there are so many input fields, I want to divide the data over several pages. But each page has it's own view model of course. That means reloading my large object every time the page changes.
To solve this, I created a DataHolderService, which is loaded as a singleton on all the view models. Then I let my viewmodels change the data in the DataHolderService and I never have to reload the data.
But I wonder, is this good practice? It feels a bit strange to be doing this. Are there other possibilities? Like using the same viewmodel on multiple pages?
Question 2
I would like to save my data to the database so it persists between sessions. I have a SQLite database and am able to save the data using a button. But if the user forgets to use the save button and the app is put in the background until the system eventually kills it, the data would be lost.
I therefore added a timer, which periodically saves the data to the database. But I can understand that this isn't very good practice. What would be a good way to save the data back into the database without having the user needing to press a save button? Is there an event/function that will fire before the view model is disposed?
Its a bit hard to understand exactly what you are trying to achieve, however.
Is it not better to use a list of questions rather than spreading it over multiple pages?
We have created a similar page recently. If your data is shown as a checkbox/radio buttons/spinner etc, we save them immediately when the value has changed.
For saving text, we use a 1 second timer that starts when the user starts typing, is reset if the user changes the text within that time and is saved otherwise.

How to Remove No Longer Used OData Bindings?

Assume a page that shows a complex data structure (for example, an article with many details). This view will be reused from time to time by rebinding it to different articles.
Now, I noticed that the ODataModel keeps all used article entities in memory (also if they are no longer bound to any control).
This will lead to two issues:
Memory consumption increases over time (if application will not be reloaded).
If the application forces a refresh of the data model, all entities will be loaded (also not used).
The second issue seems to be the bigger problem. It slows down the speed of the application.
I have not found a solution for that problem. If I use refresh(true, true) it seems all data will be reloaded.
Is there an way to clean the model?
Edit
Lets say you have a list of thousands of articles. User can click on one of the articles and will navigate to a detailed screen of that article.
The OData model in client side will cache this. To see it, do something like:
var oModel = this.getModel("modelName");
look with the debugger into oModel.oData.
If the user now navigates back and chooses the next article, this will be cached as well.
If user does this 1000 times, all articles are now in the model.
If you trigger a oModel.refresh(true);, all these data (of 1000 articles) will be reloaded not only the one bound to the view.
Now my application is not about showing article information. It's a more complex structure with subitems. Each time user is visiting this page, more data will be cached (and re-fetched in case of a refresh call on the model).
Edit 2
The function updateBindings(bForceUpdate?) seems to help a little bit.
Anyhow, the data accumulation is still there in the ODataModel class.
That means: Each visited data path will stay in memory since the next reload (F5) of the full page. If someone uses such an application over a day, the data accumulates and a refresh call on the model will read all data again, if still bound to a view or not.
Try deleteCreatedEntry(oContext). Even though this is not the supposed use case for this method it might work to delete an entity from the model without triggering a backend request.
You could also try if updateBindings(bForceUpdate?) only triggers an update on actually bound entities.
1) I do not really understand your problem here. What is it exactly that you do? OData always holds the result of your request plus a queue of changes to that request. If you create lots of entries while your application is running, of course the memory consumption will increase. If you want to revert back to the original request you can use resetChanges(). THis way the used memory should decrease again. But you lose all your changes to the model.
2) Maybe you should look into Odata filtering (http://www.odata.org/getting-started/basic-tutorial/) so that you only load the entities you really want. If you only want a part of the entity loaded then you should maybe redesign your entities to avoid a lot of overhead.
It is hard to speculate what your exact problem is.
Well, if you know exactly what are you doing, you can try something like this:
this.getModel("modelname").aBindings = []
Better solution would be go through the aBindings array and remove redundant bindings.

iOS Asynchronous NSURLConnection triggering behaviors on different views than the one that call it

Me and my team are currently rookie developers in Objective-C (less than 3 months in) working on the development of a simple tab based app with network capabilities that contains a navigator controller with a table view and a corresponding detailed view in each tab. The target is iOS 4 sdk.
On the networking side, we have a single class that functions as a Singleton that processes the NSURLConnection for each one of the views in order to retrieve the data we need for each of the table views.
The functionality works fine and we can retrieve the data correctly but only if the user doesn't change views until the petition is over or the button of the same petition (example: Login button) is pressed on again. Otherwise, different mistakes can happen. For example, an error message that should only be displayed on the root view of one of the navigation controllers appears on the detailed view and vice versa.
We suspect that the issue is that we are currently handling only a single delegate on the Singleton for the "active view" and that we should change it to support a behavior based on the native Mail app in which you can change views while the data that was asked for in each one of the views keeps loading and updating correctly separately.
We have looked over stackoverflow and other websites and we haven't found a proper methodology to follow. We were considering using an NSOperationQueue and wrapping the NSURLConnections on an NSOperation, but we are not sure if that's the proper approach.
Does anyone have any suggestions on the proper way to handle multiple asynchronous NSURLConnections to update multiple views, both parent and child, almost simultaneously at the whim of the user's interaction? Ideally, we don't want to block the UI or disable the buttons as we have been recommended.
Thank you for your time!
Edit - forgot to add, one of the project restrictions set by our client is that we can only use the native iOS sdk network framework and not the ASIHTTPRequest framework or similar. At the same time, we also forgot to add that we are not uploading any information, we are only retrieving it from the WS.
One suggestion is to use NSOperations and a NSOperationsQueue. The nice thing about this arrangement is you can quickly cancel any in-process or queued work (if say the user hits the back button.
There is a project on github, NSOperation-WebFetches-MadeEasy that makes this about as painless as it can be. You incorporate one class in your classes - OperationsRunner - which comes with a "how-to-use-me" in OperationsRunner.h, and two skeleton NSOperations classes, one the subclass of another, with the subclass showing how to fetch an image.
I'm sure others will post of other solutions - its almost a problem getting started as there are a huge number of libraries and projects doing this. That said, OperationsRunner is a bit over 100 lines of code, and the operations about the same, so this is really easy to read, understand, use, and modify.
You say that your singleton has a delegate. Delegation is inappropriate when multiple objects are interested in the result. If you wish to continue using a singleton for fetching data, you must switch your pattern to be based on notifications. Your singleton will have responsibility for determining which connection corresponds to which task, and choosing an appropriate notification to be posted.
If you still need help with this, let me know, I'll try to post some sample code.