I have created a recycler view with thumbnails generating in real time. My problem is that I need to preload 50 items (thumbnails) ahead of the currently visible ones and I can't seem to find the appropriate way of doing so.
I know that preloading can be done with getExtraLayoutSpace() from LinearLayoutManager but it doesn't work for me. If you look at this extra layout space implementation in the Android code, you'll see that it is a space available only in the scrolling direction. When changing the scroll direction, all of the items required to be preloaded in the new direction are prepared and the old ones are not available anymore. This causes a very noticeable hang when changing scroll directions in my case since I am trying to preload a lot of items - 50. I am doing the loading of a thumbnail in a separate thread but all the items are layouted obviously on the UI thread (which seems to cause the hang).
I am also NOT interested in third party libraries because I've written a lot of code making everything work with the basic implementation of recycler view and I don't have time for a lot of refactoring.
Do you know of any other ways of preloading items in RecyclerView? Maybe somehow tweaking the LinearLayoutManager? I sure hope you know of a good way, so I can evade implementing elaborate caching of thumbnails.
Related
I am trying to achieve a gridview with a different number of items in each row, depending on the width of each item. I want it to look like the one on the Medium app, as shown below:
How can i achieve this?
You can approach the problem in two main ways:
Use ScrollView with a Linear- or RelativeLayout inside. Then you would add the items in your code, measuring each and putting them into new rows when required. This will require some logic to be created, but is achievable. The ScrollView will take care of the scrolling in case the contents exceed the screen height. The problem with this solution is that you will not have a recycling mechanism, which can lead to problems with memory when the list gets long.
Use RecyclerView! :-D One of the awesome features of the RecyclerView is the fact that while providing the standard Adapter-based concept of the list of items, it also allows you to implement a custom LayoutManager. Create your own implementation of LayoutManager which positions the items based on their measured with and you are done, the RecyclerView will take care of scrolling and recycling the items for you! :-D This will take some getting used to, especially if you have no experience with RecyclerView, but the whole thing should take no more than several hours and is, in my humble opinion, really worth it.
You are free to choose either, but the second approach is more modern and, in general, easier to implement. In general, you should learn to use the RecyclerView, it helps a lot and is quicker to implement than the good old List- and GridViews, once you get the hang of it.
I have this situation I wanted to discuss:
I have a listview that it's purpose is show 25 stores.
For the design I want I have:
2 layouts, the first one has:
1 big photo of the store (downloaded from a database).
1 icon if the store belongs to the best rated stores list (that icon is on my app)
1 textview (downloaded string)
the second has:
3 textviews.(downloaded string)
Everytextview has a custom typeface.
As you can Imagine, this is a huge task for each item.
My main question is:
Wouldn't I get a much better performance if I downloaded everything and instead of making a listview I populate a scrollview with this data?
It might take a bit more to create the layout but probably it would be smoother scroll or am I wrong?
You can do the same with ListView (download everything and display), but I don't think that "downloading everything" will actually bring any performance improvements (except you're talking about cache).
ScrollView will lead to much worse memory performance as you'll have to create and keep 25 views at once. On contrary, ListView reuse the same views while scrolling which will result in creating approximately as much views as it can fit on the screen.
With ScrollView, if dataset changes, you have to somehow repopulate your 25 views. In worst case recreating all views.
Moreover, going with ScrollView you'll have to deal with 25 big photos in memory at once which will probably give you nightmares for a few days.
From my experience, if the number of elements in the list is less than 50 and the layout is not using too much memory, then you might be better off using a scrollview.
ListView is designed for much bigger dataset, and it's designed to reduce memory usage rather than performance. There are tons of work that Google put into it to optimize its performance. Together with viewholder pattern and modern hardware, and the perceived performance is close to fully populated scrollview.
But again, why need Listview if the dataset is small enough that doesn't affect memory usage? ListView is tricky to use when combined with fancy animation due to the underlying funky optimization done by Google.
What I have learned from a similar problem is that the scrollview is smoother that the listview. My case was to opt one for the navigation drawer, because smooth inflation and scrolling in the drawer has direct impact on user experience.
I first adopted the listview but it was by no means smooth. Then I found that found here that google developers use scrolview instead of listview for the drawer that works smooth for me either.
But if lazy loading of the list items is what you require(not in my case), then you should go for listview.
Currently, I am having a ListView with different list item view for each row (Most cases Different).
I am having 6 different item layout, I will add more in future, and I will have only like 5-15 list items, some time may be less and may be many in other cases.
Some item views contains:
ViewPager
ListViews
ImageViews
Texviews
Gridviews
CAROUSEL
Webviews
As this is dynamically generated depends on data, I am facing following issues :
Scrolling Slowly (Some Times)
List Item height
Performance
Is RecyclerView the best solution in this case?
Without seeing your code to identify specific concerns, it's hard to address specific reasons why you are seeing such performance problems. Such as, are you properly using the ViewHolder paradigm? Or are you inappropriately loading stuff on the UI thread when it should be loaded on a background thread? Android has a small section talking about scrolling smoothly with a ListView you should check out. That aside,based on what you have mentioned so far...I think you major problem is design.
Problems
If your ViewPager is using a FragmentPagerAdapter...then that will definitely be causing a lot of overhead and performance drag.
ListView: You should never ever place a ListView within another ListView. This will cause all sorts of problems. Android does not like embedding two scrollable widgets that scroll the same direction. Even if this worked, it'll cause some major performance problems.
GridView: Same goes with the GridView. You should never ever place a GridView within another ListView. Even if this worked, it'll cause some major performance problems.
If you're ImageView is loading some large graphics, it should be on a background thread and not the UI thread. Else you'll get some slow performance
Carousel - I have no idea what API this is but if it scrolls vertically, then it's a no go.
WebViews are a very heavy weight object. I can definitely see this guy slowing things down, especially if it's loading a lot of content.
To build off what #Joffrey has said. There are some major concerns in your choice of UI. Based on what you are placing in this ListView tells me that you need to seriously rethink how to display your content to the user. Eg, try using a TableLayout or GridLayout instead of a GridView.
I'm working on an application which consists of many HorizontalScrollViews. Initially, everything was fine. But as the application is growing, and more images need to be loaded, I'm facing OutOfMemoryError. This is because I'm running out of native memory. Therefore, I want to release those views which are not visible on the screen, just like ViewPager. But, I do not want the snap effect. I want it to scroll freely. Thanks
UPDATE: I'm working on Gingerbread.
Consider using Horizontal List View, since it seems your list is actually growing and it is not the intended usage of ScrollViews. A ScrollView is suppose to have limited, and most probably static amount of child because it does not intended to dynamic release or create views.
There's lots of tutorials about lazy loading and releasing list view's items. For instance, this is one.
if I recall correctly, Images that are not on the screen are not in memory. in anyways, working with multipul ScrollViews is very bad for performance.
try reading androids blog post about efficient UI.
it seems to me that working with a hashmap for the files and with a gallery widget instead of scroll views will be faster for the user.
look at the imageLoader implementation of fedorvlasov's LazyAdapter and look at the caching methods he uses. they're very efficient. :)
good luck
What you are looking is Lazy Loading of images on horizontal scrollview. I am not sure if it is possible to lazy load the scrollview.
Maybe you can use a ViewPager http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html This uses an adapter behind the scenes and you can do the trick where you set the count to a very large number.
I have implemented a ViewPager in my app, and aside from the swipe paging, I have buttons for "Next" and "Back", with a simple onClick method with the only line being a setCurrentItem for the ViewPager.
While the paging animation is completely smooth during swiping, it is more or less instantaneous (just flips instead of scrolling) when I click Next or Back. There is no visible "scrolling" motion, or sometimes barely visible, however not even close to smooth. It does not hurt the usability of the app in any way, since the transition still happens immediately, but visually it looks a lot less appealing, and the user experience suffers.
Now, I suspect it has something to do with the app drawing the next View and therefore "skipping" the animation. My instantiateItem uses LayoutInflater and a simple switch statement to inflate each view (4 pages at most), and I am loading custom ListViews inside each case in the switch statement. The custom ListViews are at most 3 items long, with a TextView and an ImageView in each row (ImageView resource is 5kb in size). To me it seems this amount of objects should not be reason enough to slow down the paging animation.
Aside from that, I also have a custom background assigned to my app in styles.xml, and this is the background used through every activity (160kb in size).
Those are the only things that I think could be slowing down the app, since the onClick method contains only one line (setCurrentItem), so nothing aside from going to the next view is happening in the app, and the instantiateItem is the simplest implementation of the method possible that I know of.
Things I've tried:
Setting the ViewPager's setOffScreenPageLimit to 4, which I thought would pre-load the views and eliminate any loading in between paging, but in the end setting it to 0 seemed to make the thing slightly more likely to show at least a frame of animation
Optimizing the custom ListViews by using convertView to reuse old views, while it did result in more of the animation being shown, it still wasn't completely smooth, varying from "almost perfect animation" to "instant flip"
Removing the custom background, which together with the above two fixes lead to an almost good enough solution, but still resulted in flips every few steps.
The tinkering described above leads me to believe it has something to do with the views being loaded, but I've not found a good solution for pre-loading these to the desirable effect.
Knowing my newbie programming skills, I know there is a sure fire way to solve this without resorting to gimping the design of the app itself, but reading through the documentation, Stack Overflow questions, Googling for advice, I've just ran out of places to look to.
To sum up this probably too verbally descriptive post my main questions are:
Is there a way to ensure the animation of the ViewPager is executed smoothly? A separate thread perhaps? As I understand though, UI stuff should only be on the main thread, where it already is, and nothing else aside from the view loading is executed anywhere in the code when paging.
Should I be using a different way to load the pages? Would Fragments help?
Thank you for any advice.
ps. The lack of code is due to the methods in question being the most basic implementations possible, but I will provide the code if necessary.