Android compose: LazyColumn and Room with suspend DAO - android-jetpack-compose

I want to do a seemingly simple thing in Android Compose, display a large list dynamically loaded from a Room database:
LazyColumn(count) { index ->
val myItemModel = db.itemDAO().getAt(index)
MyItemView(myItemModel)
}
DAO methods should be suspend to play nice. But suspend functions obviously cannot be called from #Composable functions. I do not want to do runBlocking. I can turn myItemModel into proxy and inflate it in LaunchedEffect but then LazyColumn's scrolling is broken as it cannot predict the viewport offset position, because the items have different content and height.
What is the canonical way to display large list in LazyColumn?

Firstly, it's not a good idea to load your items from database one by one. Load some larger chunks of your data, something like 100 items at a time maybe.
The canonical way of loading data from db and displaying them in LazyColumn would be using a ViewModel. You would do the loading on the background thread in your ViewModel, publish it as a StateFlow<List<MyItem>>, collect it flow in your composable and display it in LazyColumn.
For the loading, you can also use the paging library. It is nicely integrated with Compose - there is a collectAsLazyPagingItems() function for collecting the items and items() function, which will feed them directly into your LazyColumn.

Related

Get items visible in viewport of Grid in Vaadin 8 & 10

The Grid widget in Vaadin 8 & 10 offers a method to get a Set of the currently selected items: Grid::getSelectedItems.
In a similar vein, I would like to get a collection of the items that are currently visible to the user in the Grid. Say my Grid widget holds 10 items, but only 5 are viewable because the Grid widget is too short to display them all. I want to know which of the five can be seen by the user.
This is not trivial task, I have something similar, but not exactly this case before. First of all, I would I would create custom Layout component, e.g. by extending CssLayout in similar fashion as has been discussed here ( How to make UI receive scroll events ) in addition to reporting scroll events I would report the position of the layout on the viewport (see http://www.gwtproject.org/javadoc/latest/com/google/gwt/dom/client/Element.html ). Yes GWT and client side development is required.
I would use this layout as wrapper for the Grid, i.e. Grid would be in the layout. You could extend the Grid component as well. But I think doing the layout wrapper gives you nice tool that you can use with other components as well for which you need to determine, whether they are actually visible or not.
This way I can then calculate which portion of the layout is in the viewport. As you see, there are number of cases here, e.g. only bottom of the Grid or top of the Grid is visible. Then I need to know row-height, header height, etc. That enables me to calculate how many rows there are visible. I hope you get the idea. The outcome for the generic case will be rather lengthy piece of code when all possibilities are enumerated. This calculation you can do on server side.

Kendo UI Grid data bind to two table DB

I am trying to figure out two things. First, is it even possible. Second, am I on the correct path?
I am making an ASP.net Kendo UI Grid that just needs a very simple two table, inner join from an Entity Framework model. The issue is that one of the fields is incredibly large. It requires me to set the value to the json object size to max int value just to be able to return a single table result.
Because the resulting set is so large, I do not seem to be able to use a view model. It just returns a size limit error on that as well. Is there a way to return a very large dataset from two tables to a single Kendo UI grid? I have tried every suggestion from every existing answer on Stack Overflow and the Telerik forums.
I don't really think that some user need information which cannot be handled by default json object size.
May be should load first 50-100 characters from that field to grid and if user click on cell load rest of the data.
Another way is using virtual scroll or paging.
If kendo model cant handle your field size, you can add columnt to each row with view large data button and open window with text field loaded from db on click.

is there anyway to force durandal to recreate view/controls on view revisits(invoke view attched event) while caching enabled

I am using a kendo UI grid on a view, which is part of durandal 2.0 app using knockout for mvvm.
On a specific view, there is need to display a kendo grid having dynamic number of columns,
so every time view is visited, grid columns may have different count than the last visits.
Now as caching is enabled(applicable to this view too), so for subsequent visits grid rows are changing to reflect data change, but grid header(including number of columns) remains as it was during very first visit to view.
Note: if i disable caching for compose which is used to compose this view, grid loads fine with varying number of columns every time, but can't disable caching just because one control is not loading fine, and due to business needs.
so i wanted to know is there any way i can tell durandal to run viewattached event every time a specific view is visited, if not possible then is it possible that i can ask Durandal to recreate kendo grid control on every visit(so it doesn't uses what it created and having in cache of view)... i also tried always run viewattached on comose, but that brings a flicker when visiting the view hence i feel kind of disables caching for compose(but i can't do that a this compose is common for more than a view, which all should use caching)
Your viewmodel should return a constructor function instead of an object literal. But without seeing your code, it is difficult to identify your specific problem.

Movieclip: Attatching/Removing a Movieclip VS Hiding and Showing a Moveclip

I have this tool tip that is created every so often. What is the appropriate actionscript etiquite?
A. To Create and remove the tooltip moveclip when needed?
or
B. To hide and show the tooltip movieclip when needed?
With these A and B, the answer is B, because creating and then removing an object a lot of times creates a lot of garbage in the memory, which eventually leads to garbage collector calls, that slow your SWF's performance. You can easily go with a single tooltip MC, just fill it with information that corresponds to the new mouse coordinates before you show it.
There is another question, not so straightforward as yours, about how to hide and show a movie clip, either via visible property or via addChild() and removeChild() (AS3 only). If you are using AS2 or AS1, use visible property to hide and show your tooltip.
There are three ways to hide something in Actionscript : Alpha, visible and remove child.
Apha: If you turn the alpha zero the renderer always comes to this displayObject and renders it at alpha zero. So the object is always rendered you just cannot see it.
Visible == false In this case the object still exists in your displaylist. So the renderer comes to the object. Sees it's property is false and leaves it but it still exists in the display list.
removeChild This means that you're removing the object from the display list. This means that the renderer never had to even check for it. Which makes it the fastest option.
addChild doesn't take that much computing power as visible check. I'm sure you can find benchmarks on this.
If you don't have a lot of objects on yours screen and the tooltip is there every second I'd go with visible is false. In all other cases go with the third option.
On a side note, I've found it always easier to manage them with a toolTipManager. A class that makes sure that you have one tooltip on the screen because usually users only use one tooltip. So that makes things easier for me. I just always create the necessary tooltips and add them to the displaylist when required and remove them. (Not recreate them) At the same time have only one tooltip on stage.

What design alternatives are there for nested page controls?

In our primary application, we have a form that will allow us to do cross tab analysis of data in four different ways. Presently, each analysis appears in its own page of a PageControl on the screen. Now, upper management would like us to add in a historical aspect to the form, which in other areas we would use a PageControl to do, but nesting two of them seems like a bad idea to display the periods and analyses tabs stacked on top of each other. Does anyone have any suggestions as to how we could re-work this to look decent and work well? Thanks.
What about using the TTabset control along the bottom of the form to allow switching between the historical periods and the current data? I would also make sure that there was a visual difference in how the data is presented for historical vs current data. Like use an off grey cell background for historical data.
Use an small (horizontal) TTabSet with a vertical one.
See here (you can click on the picture to zoom). The TTabSet is shipped OOTB with Delphi. The vertical one can be written very easily if your requirements are low. If you want, I can share the code. But if you want a better vertical tab set then you can spend more time on writing or get one which is ready made from Torry or somewhere else.
HTH.
IMHO, you can use frames for each analysis result page, then you can use either PageControl or TabSet or any other visual control for loading and showing the appropriate frame.
Since frames are totally independent from the visual control you use to select proper period and analysis, you won't be restricted to tab-based controls; for example you can have a tabset for analysis selection, and a treeview for period selection.
Frames have some additional benefits here too:
First of all, their code is kept in
separate units and this will increase
code readability.
Second, you can design a base frame
and put all the controls and codes
which all these 4 analysis share into
that base frame, and in this way have
a better code reuse.
Third, you can either drop each frame
on your main form and make them load
just like before, or you can define a
container control (e.g a panel), and
based on user's selection load one of
the frames into the container control
dynamically, so reduce initial load
time of your application, and
probably reduce the overall system
resource consumption.

Resources