I have a listview with viewpager(loads images asynchronously) in each list item. Since listview recycles images on scroll viewpager instantiates again as item goes off the screen. I have also considered using LinearLayout with adapter to populate instead of listview to prevent views recycling, but im not sure it could hold large data lists. any help??
You are clear, and what is more clear is that your architecture is terribly wrong…
The reason why the views get recycled is not because Android wants you to do extra work, it's because on a Mobile device, memory is LIMITED. If something is not visible, it should go away (most of the time).
You can increase the ViewPager offset a little bit more if you want something to stay for longer but the truth is that your image loading library should cache the images to the point where the next time you recreate them, they are instantly available, if there's memory to keep the cache alive or they should be simply re-downloaded. Welcome to Mobile Development.
Take a look at Picasso for example (on how to load images and cache them the right way).
Related
I have a Custom Adapter for the ListView. The Layout has three images, some text. When loading the Listview, it takes a while, because of the images. Its something like Posts.
Same app in iOS is loading very fast, I think that UITableView works different than Listview.
Is there a way, in place to load all posts, only load for example 3 posts and when the user scrolls the Listview down, load the next 3, scroll down, load the next 3 and so on. This could give a better performance.
Normally, android listview work that way. Let's say there are 5 views that user can reach at the moment. ListView creates 9 views and when user scrolls it loads the bottom ones. You can think it this way. Your main problem is how are you loading your images and create the custom view. There is a common pattern for custom adapters which handles the fast recycling views(ViewHolder pattern). You should checkout the link for ViewHolder pattern. https://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html
It probably loads slow because the images should be resized every time, if you could save thumbnails it would go much faster.
Have you tried to use Recycler View instead? As long as I know using the Recycler View is the best practice nowadays. You can find a very good tutorial here:
http://www.vogella.com/tutorials/AndroidRecyclerView/article.html
You use the Recycler View almost the same way you do with List View: adapter, viewHolder, etc. It's good to mention though that you need to pay special attention to the use of the LayoutManager since the Recycler View it itself doesn't "know how to draw" the stuff on the screen.
Much Application is a chat program like whatsapp. So it doesn't need to display all the messages at once. Only the last messages should be shown to the user at the startup unless user scrolls and view the past ones.
I have a ScrollView that contains a large (around 1000) amount of elements(messeges). So its not much efficient performance-wise because it loads and displays all the elements at once.
In most cases its useless that it loads the entire history of msgs.
(I have think of splitting these msgs into sections and manually choosing to load them only too)
Is this functionality provided built-in with ListView or RecycleView.
I mean though we load all the elements to ListView, does it have a capability to intelligently process the elements that are shown in the screen in a particular time (or scroll level) ?
Yes, the main reason of using ListView or RecyclerView is that they provide you with View re-use. It won't load all the child-Views in one go: it will ask you to bind your data to a View whenever needed.
Is this functionality provided built-in with ListView or RecycleView.
I mean though we load all the elements to ListView, does it have a capability to intelligently process the elements that are shown in the screen in a particular time (or scroll level) ?
Yes, that's exactly what ListView does. It will be slower to scroll with it, but it will take just the necessary amount of memory.
I'm trying to add a GridView of images (ImageView) for my android application. I've successfully implemented lazy loading and caching of images and all of my high quality images work flawlessly when I have a simple GridView. However, the problem occurs when I try to nest my GridView inside a ListView.
When I simply have a GridView, the app only has to keep reference to images that are currently being rendered on the screen. But when I nest a GridView of, say 100 hi-res images, inside a ListView, the app tries to keep a reference to all 100 images, when only 20 of them are being rendered on the screen at the time. I found this out through my Log output, where the app would print a message every time an image is "read". I would see the app read 20 images that are being displayed on the screen, but then it would keep going and read more images. When it reaches around 100~ images, the app would run out of memory and crash. This behavior does not happen when I have just the GridView; the app will just read 20 images, and load more as I scroll the screen.
How can I make it so that my ListView does not try to load all elements inside a child view (especially the one that's not being displayed on screen)?
Thanks!
EDIT:
For those wondering why I would want a GridView inside a ListView, it's because I'm trying to create something like this:
Except I'd like to have it in a ListView, as opposed to ExpandableListView.
You are getting this Exception because in an expanded GridView all the data is loaded in memory, if your data is too much it will cause OutOfMemory Exception.The solution is: divide your data in small parts and then try.
You can not nest scrollable Views in Android. Components such as ListView, GridView, ScrollView can't be nested into each other.
You should take a look at Fragments (http://developer.android.com/guide/components/fragments.html) and stop to re-think your UI a little bit.
And... for large datasets, image/data lazy-loading is not enough... it is highly recommended that you implement a paging mechanism that would allow the user to page trough the results/content.
Let's say you'll display 20 items at a time. You will have to add a Next and a Previous buttons on the sides of the GridView UI (or you can do it the cool way with gestures)... and tweak your GridView's Adapter logic to pull only 20 items from your Model or from the Server at a time.
I found a really simple implementation of paging with a grid view among my bookmarks: http://paulononaka.wordpress.com/2011/03/19/how-to-implement-a-paging-feature-in-android/ ... I bet there are better ways to do it, but it could give you ideas.
Good luck!
I'm developing my first app and have been reading a LOT here.
I've been trying to find a solution for the following issue for over a week with no luck.
I have an Adapter that extends ArrayAdapter to show image and 3 lines of text in each row.
Inside the getView I assign relevant information for the TextViews and use ImageLoader class to download image and assign it to the ImageView.
Everything works great! I have 4.5 rows visible on my screen (out of total of 20). When I scroll down for the first time the images continue to download and be assigned in right order to the list.
BUT when I scroll back the list looses all the images and start redrawing them again (0.5-1 sec per image) in correct order. From what I've been reading it's the standard list performance but I want to change it.
I want that, once the image was downloaded, it will be "sticked" to the list for the whole session of the current window. Just like in Contacts list or in the Market. It is only 20 images (6-9kb each).
Hope I managed to explain myself.
you need to cache each image after download it, and each time the adapter need it check if its already downloaded get it from cache (disk or memory) otherwise download it.
at first i recommended you to read this tutorial from android dev site http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
or use an external lib like this one https://github.com/koush/UrlImageViewHelper
The problem here is that the ArrayAdapter is reusing the list view rows as you scroll, so as you scroll down, the top row will be reused and inserted at the bottom of the list (for performance reasons).
Your best bet here is to try to cache the images locally on your device to avoid calling the ImageLoader every time.
One pretty good library that solves this problem is ignition. It's open source and available here: https://github.com/kaeppler/ignition
Take a look at RemoteImageView for a good example of the caching mechanism.
I'm currently experiencing some scrolling issues in a few of my views. The performance on the Galaxy Tab (7 inch) is rather poor. Rather than trying to explain my view hierarchy here, I was wondering if anyone had any general guidance on how to troubleshoot scroll performance issues on Android. I'm interested in any approaches or gotchas that I should be aware of when building views, and how to find the trouble spots that's causing the laggy scrolling
I these few suggestions would help you,
1- Use an efficient ListAdapter (taking advantage of the ConvertView in getView() method) as such:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List14.html
2- If you are loading images over the net, thread your loader and set images to views asynchronously.
3- And if you're rendering images in your list items, keep a cache in the form of an HashMap; i.e. HashMap where integer would be the position and Drawable would be the materialized images. Use the Drawables availabe in the Cache in your getView() method and only load images if the Drawable is null when you ask for a particular index/position.
As you may already know, list items are rendered (getView() is called) every time the the item at the index is scrolled to the visible screen; so caching images and using the convertView (the view already been created once) would make your adapter and list efficient.
You could even put some system.outs in your getView() method to see the difference.
I hope these help
Best
-serkan