Destroying Fragments - android

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.

Related

Prevent fragment re-create in viewpager

I want to prevent fragment re-create in viewpager , in default way every time you navigate to a fragment in viewpager , android creates a new instance of that fragment.
setOffscreenPageLimit(x) can fix this problem but i don't want to load more fragments in activity's onCreate. Any idea to solve this problem and maintain fragment instance after select for next time?
There are two most used classes for View Pagers are:
FragmentPagerAdapter
FragmentStatePagerAdapter
and they look alike in many ways but not all.
What you need is FragmentPagerAdapter
This will keep the Fragment as you want and not being recreated each time as the following quote say from the official documentantion:
Implementation of PagerAdapter that represents each page as a Fragment that is persistently kept in the fragment manager as long as the user can return to the page.
And also here in the same documentation:
The fragment of each page the user visits will be kept in memory...
Although remember using this, memory will be your responsibility and you will have to manage memory of your Views check the number of pages you are having first if they are many, its not a nice idea to display 50 pages this way. Only may be less than 10 (Tabs may be its the best choice). You are good. Memory management is the only thing to take NOTE here as the documentation itself say:
This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider FragmentStatePagerAdapter.
So change your adapter to FragmentPagerAdapter and your fragments will be kept in memory not recreated.
Try setting Fragment.setRetainInstance(true). If you use FragmentPagerAdapter, this will cause an existing fragment to 'live' and not get re-created. It will to get detached and re-attached instead.
Try this, where you set the view pager adapter
viewPager.setOffscreenPageLimit(numberOfFragments)

Avoiding the default loading of fragments in a view pager

i am new to android. i noticed that on implementing the adapter of the view pager the getItem() will result in returning two adjacent fragments. How can i skip this default loading and load only the fragment in the current page. Please help me.
You should not do that. Please note that when swiping to next page two fragments are visible at the same time so they have both be created.
You can use ViewPager.setOffscreenPageLimit(1) for this. I've used that to keep all my three fragments alive. I Don't know what happens if you set it to 1.
Confusing, this is from the documentation. It says this value defaults to 1 but when I was working on that I got always two fragments like you do:
You should keep this limit low, especially if your pages have complex
layouts. This setting defaults to 1.

ViewPager for displaying 5 Views at the same time or other options in Android?

I'm currently using a ViewPager with a pageWidth of 0.2 to display 5 Views at the same time. This logically requires an offscreen-limit from 7, to have a smooth transition between the views.
In the beginning I used a FragmentStatePagerAdapter but I was worried about the memory-consumption and the performance. This was the reason why I now only use a PagerAdapter to display my views.
What I want (and what I have):
<<-- View | View View View View View | View -->>
Is there any other approach in android to handle this? I thought about using a LinearLayout with a ScrollView but I need to "stick" to the Views after swiping. And I really like the custom-page indicators of the view.
Furthermore: Shall I save the views (of the elements) in my objects or should I recreate them after every call (and yes, I'm removing them in destroyItem) ?
Another question: Was it the right decision to switch from FragmentStatePageAdapter to a PagerAdapter?
From the document, http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html
Implementation of PagerAdapter that uses a Fragment to manage each page. This class also handles saving and restoring of fragment's state.
This version of the pager is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.
Therefore, if you have a lot of pages, using FragementStatePageAdapter is better. FragementStatePageAdapter is more efficient on memory management.
But if you want cache 2 pages outside screen, no matter FragmentStatePageAdapter and PageAdapter, you have to cache them by yourself. Use SimpleOnPageChangeListener to catch page change event, then do some initialization for next page.
After removing the views from the container in destroyItem() keep them in an ArrayList. During instantiateItem(), first check if you have unused views in your arraylist, if so, use that one. If not, inflate one.
The garbage collector may or may not have collected the view, so you need to do a pre-check before you can use it.

Getting data (asynchronous) and populating ViewPager's fragments

I have an activity with a ViewPager with a variable number of fragments (tabs).
Upon start the activity checks if the associated (complex) data has been loaded. If it hasn't it shows a progress bar view and starts an AsyncTask which fetches the data. Depending on the data the activity creates a number of fragments (tabs) and gives each fragment a sub set of the data.
I currently hold references to the fragments (I know that it is discouraged) and I run into all sorts of problems when the fragments gets reused - I'm giving the data to the wrong instance of the fragment.
So, is there an "android way" of solving this problem?
I run into all sorts of problems when the fragments gets reused
Fragments usually don't get reused in a ViewPager. This is not like an AdapterView where rows get recycled. Using FragmentPagerAdapter or FragmentStatePagerAdapter, a fragment represents one and only one page.
I re-instantiate the ViewPager each time (but the fragments get reused?)
Ah. That's a slightly different problem.
The stock implementations of FragmentPagerAdapter and FragmentStatePagerAdapter make a couple of assumptions:
They are in complete control over the fragments, particularly in terms of running the transactions to add and remove them from the UI
That those fragments will only ever be used by one "logical" ViewPager (IOW, recreating that ViewPager for a configuration change is fine, but that' pretty much it)
Complicating matters is that these adapters store the fragments under certain tags, and therefore if those fragments still exist in those tags, those existing ones will get used, instead of new ones being created.
So, is there an "android way" of solving this problem?
It's unclear from your question why you even need to "re-instantiate the ViewPager". I'm assuming that this is tied to some sort of refresh operation, or something else that is forcing you to go through the process described in your second paragraph.
You could give my ArrayPagerAdpater a try, as it is friendlier about external agents mucking about with the fragments. Since you control the fragments' tags, you can always be certain that you are working with the right fragment -- rather than caching them yourself, just retrieve the right one and manipulate it.

ViewPager performance issue due to invalitadion of every fragment inside

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.

Categories

Resources