I have a GridView that displays images (7 columns of images that are 166dp x 249dp) that are all the same size (there are over 150 images), and I'm using the view recycling mechanism through the view holder pattern by way of an adapter. My views are all simply ImageViews. There isn't much going on that should be slowing the scrolling on this widget (there are 21 images on screen at a time), but the thing just scrolls so choppy. What can I do to speed it up?
I spoke with some of the boys at Google during the last Google Developer Lab and they told me that GridView is not maintained very much, and that I should use ListView, laying out the rows myself in code to make a grid. This is what I did and it's now lightning fast.
Related
A performance question here. I have a recyclerView (in a fragment) that I'm populating from a database that's going to eventually hold around 16,000 items in a single table, 18 columns per record, nothing trickier than ints, decimals and varchars and the records are categorized so I don't expect to ever need loading more than, say, 300 at a time. Should I consider limiting the selects or implementing some sort of paging? I'd prefer to keep the recyclerView simple and seamlessly scrolling.
I'm also wondering about the recyclerView itself. The rows are rather complex and have two states: the default collapsed state shows 6 views including a single imageView, and upon clicking a row we get expanded state (a container goes from GONE to VISIBLE) with a total of 21 views including 2 imageViews. I care about the quality of imageViews so I'm testing it with a resolution limited at 512px for a small image (50% screen width) and 1024px for a large image (100% screen width), everything in JPGs. And because I need to track the state of rows, I have used
holder.setIsRecyclable(false);
in my onBindViewHolder in the recyclerViewAdapter, because without it expanding one row results in some of the following, recycled rows being expanded too. And I obviously want to have every row collapsed until explicitly expanded by user. So the thing is, the recyclerView doesn't scroll so smoothly, there is a noticeable scrolling lag as new rows enter the screen and the old rows leave it, or vice versa. When tested on a reasonably powerful device (LG G7 Fit) the experience is, frankly, quite jumpy. What can I do to optimize the performance (yes, I'm using 6 various sizes of images for various resolutions already). Is there perhaps a better alternative to the recyclerView that wouldn't need turning everything upside down?
FYI after an extensive testing I found that the most drastic improvement to the smoothness of scrolling is gained by reducing resolution of the images in the first (always visible) imageView.
If I have a recycler view that has a few cards and some of the cards are basically a TextView which a huge amount of text e.g. spanning 3 screens essentially as the user scrolls, are all the benefits of a recycler view essentially gone and I could have gone with a LinearLayout?
If I understand you correctly, your RecyclerView has only three items in it
If so, then yes, you are not recycling much. A ConstraintLayout wrapped in a ScrollView probably is easier to maintain over time.
If you put all the large text in one item, yes, you shouldn't use recycler. Second thing, large text rendering is a performance problem. But if you slit your large text into some smaller parts (small enough to fit 3 or 4 parts in a screen) then recycler will do the hard work for you: only render text when user scroll to it.
I am starting a new application and I am willing to use the Dashboard pattern.
For example: The Google IO app uses it:
My issue is that the amount of buttons will be more than six.
I'm not sure if I should use vertical or horizontal scrolling.
Vertical scrolling could be done with a ScrollView or a GridView but I am not sure which would be the easier way to implement the horizontal version.
I was thinking of using an HorizontalScrollView but it doesn't have pagination. It should feel similar to the tweetdeck app.
How would you implement it?
My issue is that the amount of buttons will be more than six. I'm not sure if I should use vertical or horizontal scrolling.
IMHO, do neither. Reduce the number of buttons. Watch the 2010 Google I|O presentation on this design pattern -- the point behind the dashboard is to only surface a few items.
I would go with a vertical scroll. It is way more natural to scroll down to view more content of the same view.
A horizontal scroll kind of feels like you switch to another part of the application.
I have an app that uses a gridview with vertical scrolling but I dynamically adjust the number of rows in the gridview based on the width of the actual screen so that it in landscape or in a bigger display it uses more columns and avoid scrolling alltogether in most cases.
However in my case it is more of a search results display of categories and not a dashboard. I believe the whole point of a dashboard is to have only a small number of button (e.g. max six or so).
What you could do is dynamically interrogate the screen real estate and if there is not enough room just show e.g. 6 buttons of which one is a more/utils or whatever button. Sort of like the options menu does it.. but on a bigger screen display them all.
It would be interesting to scroll based on the orientation of the device, so you would scroll horizontally or vertically if the device is oriented that way. This would let you maximize the screen real estate.
I have a very large image (a map) that I need to display. I already have the image in "tiled" format - 256x256 pieces.
Also I got tiles for several "zoom" levels.
At the moment the issue is to display the deepest zoom level, where you'd have really a lot of tiles.
For example, a medium sized map will contain 4 rows and 26 columns of tiles for deep level.
I tried approaching the problem using a 2 dimensional scroll view and image views inside it - 1 per tile.
The problems is that it crashes. When I try displaying 4 rows and 20 columns it doesn't crash, obviously it's a memory issue.
So the question here - how to display all that, taking into account limited phone RAM.
I do understand there should be a way to dealocate memory for images that are out of sight, and only display those which are currently in visible area of the scroll view, but I don't know how to do that.
Would be happy to hear any clues or maybe there's alternative approach to these things.
Thanks.
I think you might better use the grid view instead of arrays of scroll view (but I am not sure if it support side/updown scroll at the same time.
And then in your adapter, override the getView method. There you can control the recycling of your images.
The project I am doing also have issues with image and RAM, what I am basically doing is like:
image.recycle();
System.gc();
I tried doing the above stuff like 50fps with the image is like 800x400x32bit and still not running into out of memory issue. But if I take away the System.gc(), it crash immediately.
I have extended an ArrayAdapter to manage a ListView using a certain tamplate (made of 1 ImageView and 1 TextView contained in a RelativeLayout) as row of the list.
Anyway I am now facing some optimization issues. As you guys know, not all the rows are rendered at any 1 time but rather you get the rows progressively rendered when the user scrolls the list and they actually appear on the screen. Basically my problme is this:
when the list is scrolled really rapidly, the rendering engine cannot keep up with the speed and, although the images to display are cached, the placement of the images in the ImageViews of the visible rows take some time.
To be honest I was expecting the getView method to be really fast but apparently when it comes to images there are some tricks to know. Any1 wanna share ??
cheers ;)
You may take a look at my sample. It does exactly the same Lazy load of images in ListView.