I am working on and Android app which has legacy code and we are using ListView and optimizing the listview by using ViewHolder.
Our listview has different types of custom views which are a bit complext. The scrolling performance of the listview is pretty good till now.
A new requirement has come up to support Webviews in the same listview. The webview content to be loaded from disk and javascript is enabled.
The problem is that when I add webviews in list the scrolling become jittery. During the scrolling I can see that the webview content is blank as it is still to be loaded.
I think the performance degradation is due to two reasons.
1) creation+Loading of new Webviews everytime getView of listview adapter is called
2) Displaying the content of webview
To solve these issues I started caching 7 webviews and I am recycling the webviews by detaching from previous parent view and attaching to new parent view. For example if the current visible item index is 5. I will also create the webview for three next(6,7,8) and three prev(2,3,4) items and keep them in a cache based on some id of listview item content. So when there is requirement for next item say for index 6, I will simply return one item from cache and update the both from front and back to hold 3,4,5 and 7,8,9 index items.
I was thinking that by creating a pool of webviews I will solve both the problems. 1) creating new webview ever time getview is called. And by prefetching the next/prev 3-3 items I can preload url so display will happen in background.
But I can see that display is still taking time and scrolling is still jittery.
So my questions are:-
Does webview display the content only when it is attach to a window ? (In my case the webviews in caches are not attached to window and I am loading the url in them.)
Does webview display the content only when it is visible ?
Is there a way to render the content of webview in background so that by creating cache of Webview I can do smooth scrolling.
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.
Situation
I have 3 tabs and currently when I swipe between the tabs there's a lot of lag. Each tab contains a ListView that has an image of a user, and two TextViews with the user's name and a small description (kind of like WhatsApp). Earlier each ListView would also lag and not scroll smoothly, but I went through this guide from the android developers website and then I modified my app to load the images in an AsyncTask and also implemented the ViewHolder pattern. Now, the ListView loads scrolls smoothly, but it takes time to scroll for the first time. In other words, when the ListView is scrolled for the first time it lags, but then it becomes smooth. Another thing you should know is that the data that is populated into the ListView is loaded from a SQLite DB.
Hypothesis
I hypothesized that the reason for this is that even though I'm loading the images in an AsyncTask, because I'm reading content from a DB prior to setting the adapter, that DB access is causing the tab switch and the subsequent first-scroll to be slow.
Question
Will reading the DB in an AsyncTask and then setting the ListView adapter in the onPostExecute method improve my performance? If yes, what's the logic behind it?
I have a bad feeling it wouldn't make a difference because the ListView will be drawn only after the data is provided through an adapter. Here, however, we're loading the data to be fed into the adapter itself from a DB in an AsyncTask.
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).
Two questions:
a) is there any way to stop views from getting "thrown out" when you scroll? I'm fetching images from the web using the YouTubeAPI (YouTubeThumbnailView) and it takes some time to fetch these - when scrolling the images are loaded in a couple seconds after scrolling has stopped.
and b) can I withhold elements of the listview until they are completely loaded? I'd prefer the elements to render when their thumbnails have loaded.
It seems like you're going about this the wrong way. You should be fetching the images and storing them in some sort of cache (there are numerous topics on this, so I'll leave that part as an exercise) and then notifying when the data has loaded and updating the thumbnail if it's still on screen. It shouldn't matter whether the View was "thrown out"; on the next time you try to View that particular thumbnail it should already be in the cache and should be able to be loaded near-instantly.
As for the second question, you could initially set the visibility of the View that you return in your Adapter's getView() to INVISIBLE, then when you display the thumbnail, set the thumbnail and then set the View to VISIBLE.
I've got one issue with otherwise nice working ListView.
I want to load new items into the existing listView, just like in Gmail or Google Play app - I show like 15 items and when the user clicks Load next, the other 15 will be loaded, so we will display like 30 items.
Everything works fine like this, except the ImageView, which is part of the every item in the ListView and is loaded asynchronously. Every time I click load next, all the images in the existing items are reloaded.
How can I avoid this behavior? Any suggestions?
It doesn't really look well, images are loaded from the cache really fast, so it is like a short blicking of all the images.
I was thinking about overriding the notifydatasetchanged() somehow - but I would expect a method in the ListView, in which I could set whether the whole ListView should be reloaded, or just the new items.
All the items will fill_parent, so the width is not an issue.