I have a GridView with thumbnail images loaded in a separate thread. After all the thumbnails are done loading, if I scroll the grid view it's consistently slow (~5fps), until I scroll a few rows down, then it immediately scrolls extremely fast (~30fps) even if I scroll all the way up again.
If I then repopulate the gridview, it's slow again until I scroll down some more. It's not an issue of recycling the views as I am already doing that.
(Update: uploaded the correct slow trace image)
I tracked the issue to an internal view draw call. Here is the Android Studio trace for when it's slow:
And here is the trace for when it's fast:
It's clear the guilty method is android.view.ThreadedRenderer.draw(), but this is an internal call and I can't test further. From the trace, my understanding is that it's not the drawing that is slow, as the android.view.ThreadedRenderer.updateRootDisplayList() which eventually calls android.widget.AbsListView.draw() finishes just as quickly in both traces. So it must be the rest of the android.view.ThreadedRenderer.draw() that is causing this.
Looking online I found the ThreadedRenderer.java class
Things I've tried:
Forcing hardware rendering on the gridview made no difference.
Forcing software rendering on the gridview made the list always scroll very slowly.
Any ideas why this could be happening?
Well, the reason that it's a lot faster to scroll after the first time is that Android is recycling views. This means that it's taking the most time to construct the views initially.
I think you're going a bit too deep. You should check to make sure you're not downloading the thumbnails synchronously during draw. Try removing the code that downloads the images, or set the URLs to "". Essentially, try stripping down your thumbnail view until you can pinpoint what the issue is. This should help set you on the right track.
I had a similar problem recently.
You need to check the number of Layouts in your xml file.
The more relative or linear layouts you have on your scroll view the more slow it gets.
Post your xml file less see.
Related
When displaying a screen with various sections ordered vertically, where each section looks different than the other (so maybe recycling items wouldn't use an actual recycle but a recreation), would be any true benefit to use a recycling view group, taking into consideration that no large bitmaps will be displayed, instead of an plain ScrollView?
I suspect there is a performance impact when using ListView for example, that might affect scrolling, and an slight increased memory usage, maybe a delay (only when layout is measured - not that often) when using ScrollView, but are these that significant for 7 sections, for example, where 3 of them are visible at a time?
Thank you!
This is mostly speculation, but I would consider it relatively well-informed speculation.
Let's assume you have 1000 sections, each of them different from the other. My understanding is that both ScrollView and ListView will have "problems" here, though the sort of problems they'll each have will be different.
ScrollView will measure and lay out all of its children up front (which will probably be quite expensive and will probably cause quite a delay in your UI). And it will have all of those views inflated and hanging around in memory (which might cause your process to crash with an OutOfMemoryError). But if the delay were acceptable and if you had enough memory for everything, at this point your app should run perfectly smoothly (i.e. no frames dropped when scrolling/flinging).
ListView, on the other hand, will only measure and lay out those children that are currently on-screen, as well as a few extras that are immediately off-screen. So initial performance should be quite fast and memory consumption should be quite low. But you mention that each section is "different", so view recycling won't "work". In practice, this would mean ignoring the convertView parameter of getView() and inflating a new view each time. If your sections are complicated, this could easily cause frame skips during scrolling/flinging.
But you mention that your app will have only 7 sections, or about 2.5 screen's worth of UI. For such a small number, I think worrying about performance before simply trying something out is silly; I suspect that a ScrollView holding a LinearLayout holding all seven sections would work perfectly well on all modern devices.
I have an XML file with about 150 views. Yes, I know it is a lot and I did get a message from Android Studio saying I can't exceed 80 views. But I can't drop views any lower than 150. I considered using list view but it works the way I wanted it to.
The question is, will this many views make the app crash/slow the device? I've tried it on my s7 and it works perfectly fine. My lowest API is 17 which is 4.2. Wouldn't 4.2 devices be able to handle this XML without any problem?
Thanks.
The problem with having an excessively large number of Views is that Android often needs to measure, layout, and draw them, and it will traverse the entire View hierarchy to do this. If the number of Views is so large that this traversal takes more time than the screen refresh rate, you will skip frames and your UI might appear to lag or be choppy.
If not all of those Views need to be on screen at once (for example, if you are using a ScrollView to hold a very large container that the user can scroll through), then you should probably switch to using RecyclerView.
If all of those views need to be on screen at once, then you might consider writing custom Views that can display your content all at once instead of having individual Views that draw individual things. This can drastically reduce the time and complexity of the measure/layout/draw traversals.
It's difficult to suggest an approach without knowing more specifics about your UI, but hopefully that explains the issue.
I'm using a ListView to show plenty of images (endless scrolling). When I start to scroll down the list this messages floods the logcat:
WARN/View(15722): View too large to fit into drawing cache, needs 1639680 bytes, only 1536000 available
I'm having trouble to understand the drawing cache mechanism but it seems to be enabled by default as I did not enable it. I assume it would be better to disable it because it produces hundreds of warnings within seconds. But I've got no idea which view is actually causing this issue. I tried to apply setDrawingCacheEnabled(false) to all involved views but the issue remained.
Applying setScrollingCacheEnabled( false ) to the ListView did the trick.
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.