I am using the Sherlock ActionBar library and I have a SherlockFragmentActivity implementing ActionBar.TabListener (for my tabs) and I have 3 tabs...each being a SherlockFragment. When I rotate, the entire Activity is recreated and I lose all variables declared in my onCreate within the Fragment. How would I go about fixing this?
I figured I should be using fragments as tabs instead of activities...is this wrong?
EDIT: I should mention that my current workaround is to have static Lists in the Tab Activity and have the fragment push stuff to those lists on onPause (and get stuff back from them on onResume). I REALLY don't like doing this and I know there has to be a better way.
Also, regarding if(savedInstanceState==null), I've tried that and it doesn't seem to work. I think it's because the Activity that holds my Fragments is being recreated and the tabs need to be recreated.
There's a method called setRetainInstance() in the Fragment class, that you need to set to true. That'll save the instance of your fragments, and you can then check for any saved instances in onCreate().
More info available here:
http://developer.android.com/reference/android/app/Fragment.html
Related
I used to have 3 activities with 3 layouts.
1. HomeActivity.java (activity_home.xml)
2. HelpActivity.java (activity_help.xml)
3. SettingsActivity.java (activity_settings.xml)
Whenever i had to open other activities, i used animated slide-in-out intents using overridePendingIntent. In this way, all the variables of HomeActivity stayed in itself and HelpActivity's variables/methods were in itself and same for SettingsActivity. I used onCreate() in these to perform some activity specific code. and, android:onClick="fetchSarcasm" from activity_home.xml was calling specified method in HomeActivity.java. So, there were no conflicts. All the normal things, that happen in an AndroidProject with 3 activities and used intents to switch to one another, were happening as i wanted.
But now, I wanted to migrate to ViewPager instead of slide-in-out intent transitions. In this way, there will be only one Activity with an XML of ViewPager. This ViewPager and its FragmentPagerAdapter gets the Pages from 3 classes extending Fragment with relative XML layouts.
I want to ask: Where do i write my Page Specific Code for onCreate(), layoutView's onClick="" and for onChangeListeners. Because, 3 classes extending Fragment do not have any Context or findViewById() and they do not respond to android:onClick="method" in different layouts.
Do i need to mix all that code of three activities into one containing ViewPager? If so, this makes ViewPager activity pretty heavy. and, writing if(page=2){ dothis(); } seems absurd for all pages at every code point. Any checkbox(view) that is in page 3, becomes null in other pages.
I know this might be a stupid question. I have spent almost 4 days trying to achieve something but i can't. Also, this is just my 2nd month in android, so i am new. I do not use Action Bars, Tabbed Bars or Navigation Drawers.
I am available on SO Chat too if you want to ask something more.
I just want to know how do i merge all the work i did when I was not using ViewPager.
If you're only reading the Preferences once for each Fragment, you can move your previous Activity.onCreate() logic to each Fragments onViewCreated() or onCreateView(). Read your shared Preferences there and set your Checkboxes accordingly.
Fragments inside a ViewPager aren't necessarily recreated on each page change. You can change how many Fragments are instantiated at a time with ViewPager.setOffscreenPageLimit(int).
Fragment Lifecycles explained
I have an android app in which I want to dynamically add and remove Fragments to a ViewPager during runtime, and preserving the Fragments on configuration changes.
Thus far I have implemented a FragmentStatePagerAdapter, holding my Fragments in a list with methods add, remove and replace to manipulate my Fragments. Basically, all they do is insert or delete a Fragment in the list and then call notifyDatasetChanged(). I insert the staring Fragment as a new Fragment during the Activitys onCreate() method.
I know want to preserve my Fragments during configuration changes. Currently, when I change my screen orientation, all my currently Fragments are deleted, and I get back to the starting Fragment, naturally because the Activity is recreated, and the Fragment and the Adapater are reinstantiated during the onCreate() call. I was trying to save the state of the Adapter with the Adapter.saveInstance() during the Activitys onPause(), but when I try to restore it via Adapter.restoreInstance(), I get an empty adapter.
Can anyone give me a hint on what is the correct way in Android to save state a FragmentStatePagerAdapter?
To save the state of the current fragment, i think first of all you will have to check which fragment is currently added/visible in the container activity. Once you have that fragment, simply use onSaveInstanceState() method of the container activity to save the instance of the current fragment.
For code snippet please follow this link.
I am implementing Tab Layout with Swipeable Views in android. For implementation I had followed
AndroidHive
and
Tabs and swipe views.
But with both, I am facing the same problem. I am having 3 fragments but when my application run, onCreateView of 1st and 2nd Fragment called instead of only of 1st fragment's. When I swipe and go to 2nd fragment, onCreateView of 3rd Fragments get called.
So, whatever I code in 2nd fragment execute in the first fragment view. I researched and came to know that it happen to keep the next fragment into memory for smooth animation. But I am wondering, where I would code in the fragment so that it will execute only once or how to restrict Fragment getItem() method to be called only once. What can be the solution for this?
According to the Fragment's documentation you can implement the onCreate() link:
The system calls this when creating the fragment. Within your implementation, you should initialize essential components of the fragment that you want to retain when the fragment is paused or stopped, then resumed.
This should fix your problem, because i guess you now only use the onCreateView which might be called more than once.
For more information you can check the Fragment's lifecycle or documentation
Let's say I have an Activity with a certain content. Now I need to create a new screen with tabs, so that the content of this activity will become the content of one of those tabs. I know I can do tabs with ViewPagerIndicator, for example. But, in order to do that, I need the screens to be implemented as Fragments. The problem is that the current implementation relies heavily on the Activity hierarchy (lots of calls to methods on the superclass, etc). So, I cannot simply make the current class extend Fragment. What other options do I have in this case?
Now I need to create a new screen with tabs, so that the content of this activity will become the content of one of those tabs
Having activities be the contents of tabs has been deprecated as a technique for nearly three years.
The problem is that the current implementation relies heavily on the Activity hierarchy (lots of calls to methods on the superclass, etc). So, I cannot simply make the current class extend Fragment.
Replace most of those "calls to methods on the superclass" to use getActivity(). as a prefix, where relevant.
What other options do I have in this case?
You could remove the activities entirely and rewrite your UI as custom views. This would be more work than converting them to fragments.
Or, you can just not do tabs.
So, I cannot simply make the current class extend Fragment.
That sounds like you have a huge Software architecture problem. In this case you may consider a complete rewrite (or more a copy & paste rewrite)
Normally it should be really straight forward to "convert" a Activity to a Fragment.
Fragment has nearly the same lifecycle callbacks:
Activity.onCreate() ---> Fragment.onCreateView() etc.
You can also access the parent Activity of the Fragment by calling Fragment.getActivity().
I don't know your code, but it should be definitely possible to "convert" Activities to Fragments.
You may split your activities code in own classes and inject them to the Fragment.
There is not really a alternative I could recommend you!
If you want tabs, use a ViewPager with Fragments. DO NOT USE OLD DEPRECATED STUFF like TabActivity
I have fragments in a FragmentActivity, that has an ActionBar and Tab navigation. My problem is that I want to call a method on the Fragment. I cannot use findFragmentBy[Id|Tag], because the fragments are initiated and attached by the adapter, and it assigns a custom tag. I saw several solution based on keeping references to fragments, but I really want to avoid keeping any reference to my fragments, as they are handled by the FragmentPagerAdapter. Now I have everything in my Fragment (which is a workaround in my view), but the question still bothers me.
What is the best way to access a fragment instance from my activity, not added by my to FragmentManager, but the FragmentPagerAdapter?
I solved this problem by writing my own Adapter. Since they are pretty straightforward, they are easy to be implemented.