Is this possible to preload Fragments for ViewPager so that there's no lag when user swipes to next page? I've been trying two kinds of adapters but there's no use in switching from Fragmentstatepageradapter (I am using fragments to generate N pages) to fragmentpageadapter. I've got a lot of bitmaps to load in my pages. Setting viewpager offscreen pages doesn't help. Is there a way to preload them and inflate in backgdound? I know this is a silly question but I am a bit desperate about performance. Basically in my app when user scrolls to next page there is kind of lag, just between pages, and it's so annoying... Please help or point the right direction. I am targeting Gingerbread so I need to use that what Android Support gives.
Is this possible to preload Fragments for ViewPager so that there's no lag when user swipes to next page?
Sure. Have your adapter preload the fragments. You are responsible for returning fragments in getItem() -- whether those are "preloaded" or not is your job.
That being said, your problem most likely is not with the fragments themselves, but something that the fragments are doing. For example, you "got a lot of bitmaps to load in my pages", and if you are doing work related to those on the main application thread (e.g., using BitmapFactory), you are causing your own lag.
So, instead of racing off to "preload" stuff, a talented programmer would find out specifically what is causing the lag, using tools like Traceview. Then, and only then, would a talented programmer start working on a fix.
Related
I am using a view pager to show a list of images, it works fine but the main issue is that when I swipe between images, there is some kind of fading between images.
for example if I have 5 pictures and the first one is visible when i swipe the second one is visible directly.
if i decided to swipe faster, it shows white screen then the image appears "moving from first to third quickly - as example".
I think the fragment is being recycled - is there any way to avoid this ??
It's hard to tell with no details on your implementation, but just to answer your last question (I'm not sure if it will necessarily solve your problem) - if you are using a fragments in your ViewPager and are currently using a FragmentStatePagerAdapter, you can switch to a FragmentPagerAdapter, which will keep the fragments in memory (although it will of course use more memory, so you might not want to do it if you have a large number of fragments in your ViewPager). You can also specify how many offscreen pages for the ViewPager to keep using
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(2);
In the above case it would keep 2 pages on each side of the currently viewed page. Sorry, I would have confirmed the specific problem with you before posting this answer, but I don't have the status yet :(
For couple of days, I have a question in my mind that couldn't find any answer for. Right now I have an android app that I use 1 fragment and a view pager with 3 fragments. What I wonder is, is there any performance difference between those two? Will using of fragments provide me less cost than using activities? What would be good for RAM/CPU of device while changing layouts; skip from one activity to another or skip between fragments of viewpager? Because if I use activity, than everytime a window will pop up. But in viewpager's fragment I will stay in one activity and will change only pages. Will that provide me performance on device or is just an UI issue?
Thanks in advance.
A ViewPager works in this way: Let's say it has n pages, or Fragments. If you are on index i, Android will ensure Fragments i-1 and i+1 and their Views are instantiated. As you page from side to side, subject to memory and the "Don't keep activities" setting, you will keep instantiating Fragments until all Fragments are present in memory. When you side from side to side, Android uses OpenGL to smoothly slide one Fragment's View over onto the screen while sliding the other out.
Contrary to some other answers, Android does not instantiate all Fragments when the ViewPager starts - instantiation is lazy. In addition to the default behaviour described above, you can control memory use using the setOffscreenPageLimit().
This is the key difference from the older Activity stack model which instantiates Activities only when called.
There are several consequences:
When the ViewPager is first shown, the CPU will be more active since it has to instantiate the Fragment being shown and those off-screen to the left and right (2x or 3x the equivalent work)
Since all the Fragments stay in memory, memory use will be (slightly) higher. If your Fragments don't use much memory, the difference in memory usage is trivial.
If there is memory pressure (or "Do not keep Activities" is on), then only 2 or 3 Fragments are kept; other fragments are suspended so you need to ensure the onSaveInstanceState() is implemented correctly. When the user slides back, the Fragments will be resumed. However, resuming a Fragment is less CPU intensive than creating the equivalent new Activity
Once the Fragments are instantiated, as the user slides from side to side, CPU use will be lower and (most importantly) the UX will be much smoother since the Views are already present and rendered in memory.
Communication between Fragments is relatively easy using the parent Activity as the communication hub.
One other point: The ViewPager's UI metaphor is different to the Activity stack. When weighing which approach to take, you probably should value the UX more than the implementation details (CPU and memory) unless the implementation costs are extreme.
There is the difference b/w those 2:
If you use fragments then the first time your activity load, it will load ALL of your fragments as once (a huge memory consumption here if you have many fragments, but in your case, 3 fragment maybe acceptable). But as it load ALL as once, you can move back and forward without delaying (it's obvious for a view pager anyway). So if the requirement allow users to move back and forward your pages then Fragment is the choice, the problem is how you can manage the memory consumption to avoid memory leak or out of memory exception.
If you use activity (many activities) instead of fragments then the memory will stack up every time you move forward and unstack every time you back. It seems more efficient but the problem many occurs if each activity contains a large image which take a bit long to load. Therefore, every time you move back or forward there WILL be a delay which is not nice for user to observe. So, if the requirement only allow user to move forward, the using activity instead of fragment is obviously right.
In conclusion, depending on your application requirements and how you manage the memory issue to use Fragment or Activity. These are only my experiences and observations, I'm not guarantee that's true in any cases. There maybe a better explanation that I haven't know yet. Hope this help and English is not my native language, if you don't understand leave comment below.
I have an android application where I followed http://developer.android.com/training/animation/screen-slide.html to setup.
However, I have quite a few fragments in the ViewPager (not at once) and I'd like to destroy them when I'm not on them. To put it into perspective, I have one fragment that gets created every time the ViewPager's getItem(int position) is called - which is around 365 times (one for each day of the year). All was good until I added an ImageView to one of the pages (12 in total at the end of it...) and now I'm running out of memory if I try view 3 of those page fragments.
My question is, how do I remove/destroy the fragment when its not the current page? I tried popping the BackStack of the FragmentManager, but that didn't work (it doesn't seem to have anything in the BackStack, but then again - I could have been calling it in the wrong place which was the getItem() function)
I'd provide code, but its quite a lot to look through for the important parts. It has the exact same structure as the Tutorial in the link above.
Thanks
If you get memory issue after adding imageViews to pager, why not focus on the memory aspects of the bitmap you construct for the imageView just added to your app?
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Note that pictures from device cameras can be very, very big and can cause memory issues very quickly and , IMO you should focus first on that.
IMO , the standard ViewPager and standard Adapter are OK at managing memory, even if you have lots of Fragments that you cycle through the pager.
And, its a little complex to take on the issue of explicitly destroying pages, reloading fragments in a ViewPager due to the amount of detail in collaboration among the pager and the adapter.
If you want to take on the complexity of the adapter and pager yourself, you will need to get into the source code for the pager and for the adapter you select:
* {#link android.support.v4.app.FragmentStatePagerAdapter},
* {#link android.support.v13.app.FragmentStatePagerAdapter};
As you can see from many posts on the topic of managing fragments in a ViewPager, its not enough to simply call 'destroyItem()' on the adapter or to simply remove a fragment from the ListArray bound to the adapter before calling notifyDataSetChanged() on the adapter. You also must know exactly how the operation of getItemPosition works along with the ViewPager in order to get the result you want.
It will probably take lots of time to work through the ViewPager approach .
Solve it if you can by first focus on the bitmaps.
Offtopic: thank you for your time and sorry for my English.
The problem is the lag when swiping on ViewPager.
The configuration used is a TabHost with Tabs (and dummy content), ViewPager with four fragments and FragmentPagerAdapter to manage it.
All 4 fragments have a list, some with other widgets in the layout. The thing is 2 fragments, or the 2 list in those fragments are quite heavy. The list items are LinearLayout with ~10 weighted items inside binded with a CursorAdapter. I know here resides the big problem, but I have struggled my small head to get an approach to this "percentage width" list item without any luck.
But, after some logs, I have figured out that the 3 managed fragments are "invalidated" during every swipe. I mean "invalidated" because what I see is every list binding items many ( a lot of ) times. And because of the redrawing of the 3 list, including my 2 heavy lists, the lag occurs.
2 things more to point of my code: I'm using cursor loaders, that I'm sure are not the cause of recreation because loader callbacks aren't arise on swipe.
On FragmentPagerAdapter.onPageSelected I'm only updating the current tab.
Setting ViewPager.setOffScreenPageLimit(3) to keep 4 fragments alive do things worse. Even when I swipe from fragment 3 to 4, the list on first fragment is re-rendered, what I really don't want and don't understand.
My workaround is using the onPageSelected to set the visibility of current list view to Visible and the others hidden. With these approach the lag disappears (let's say 95%), but I can see, when I scroll the empty list view before is created.
I would like to ask, if I'm wrong at some point, maybe missing an important idea. If anyone has a possible solution, maybe avoiding those recreations (I don't know how) or, if other people is getting same, and there is nothing to do to solve it.
I will try to take I look to ViewPager source, but I've just opened the file woouu..
I will try to get a test project with this issue.
Thank you very much.
I want a Viewpager that shows loading while content is coming in from the background. Basically I expect the first View to be loaded, but View+1 and View-1 will still be loading. If the user swipes to either side I want them to be presented with a spinning dialog while it loads
Would I just add AsyncTasks into the ViewPager with some conditions determining when they will run? I dont want too many AsyncTasks to be loading as the viewpager will have many views off to the sides.
I think the Trulia app does this, it is similar to what I am looking for. Apartment image viewing shows a loading screen while the images are loading in that viewpage.
Also for the record, can I just treat viewpagers like onCreate functions of an activity? That would really clear things up
Insight appreciated
Have a look at the supplied FragmentPagerAdapter if you want to perform more Activity-like lifecycle management of each page.