I'm really sorry, but atm I can't test any code. But I have a question. How should we work with fragment manager? I got an error when I was trying to add fragmentA, then fragmentB, and then again A. I got an error : fragment is already added. And here is the question: should I call transaction.Add at launch and then replace it with others fragments or I shouldn't.
Thanks for attention and sorry for my English, it is not my native language
You can add it if you want but you on first launch you can actually just use .replace even if there isn't a fragment currently loading into the frame and it will still work.
Related
I have looked at the solution below, and it looks strange to me:
https://stackoverflow.com/a/13074955/499206
Is it really necessary to explicitly remove the fragment using a fragment transaction if I pop it from the backstack using PopBackStackImmediate()?
Shouldn't the framework handle it for me?
At least I don't see the fragment in the fragment manager anymore after PopBackStackImmediate().
I want to check if the Activity I create in a test is showing a Fragment. How can I do this? I've tried searching through Stack Overflow and Google but I couldn't find anything.
You need to find the fragment by id with
activity.getFragmentManager.findFragmentById(R.id.your_fragment_container);
If this returns something different from null, then it means that your container has a Fragment.
Problem
onSaveInstanceState is being called on device rotation for a fragment which has been replaced in a fragment transaction. This is causing an IllegalStateException with the message "Content view not yet created.
Research
I have found the following two answers which seem most relevant
Using onSaveInstanceState with fragments in backstack?
onSaveInstanceState of previous fragment is called on-orientation of current fragment
What I've tried already
Following the answer to the second question I have removed addtobackstack from the fragment transaction but am still getting the error.
I read the accepted answer to the first question but am not sure how to get a fragment reference within onSaveInstanceState for the activity. I also don't particularly want to save that fragment, when the user leaves that fragment it's state does not need to be saved.
I have also tried adding if (getView() != null) {...} to the onSaveInstanceState in the fragment but this made no difference.
Questions
Why is onSaveInstanceState being called even though the fragment hasn't been added to the back stack?
Is the right approach to somehow kill the fragment when the user is done with it?
Is there a different solution?
Thank you in advance for your help.
Andrew
Edit
If I remove addtobackstack(null) from the transaction which adds the fragment and the one where it is removed the problem goes away, but then so does an important piece of functionality... I could add that case to my onBackPressed override function but it seems a bit of a hack, and not in a good way.
Adding an isVisible() check onSaveInstanceState of the fragment in the backstack should work.
No need to retain instance state when it is not visible.
In my application, I have tabbar functionality. In one tab i am displaying server data in lisview, and on clicking on that detail page for that list item will be open in new fragment.
But when I press back button from that detail page, every time oncreateview called of previous page, so every time listview created and new fetches new server data. So how to prevent such and just display previous state when back button press?
I know it has been too long to give this answer but what i am guessing is you are replacing your fragment with other one. I mean to say is you are using
ft.replace(R.id.realTabContent, fragment);
to move to other fragment which is you are using in your onItemClick so simple solution is use
ft.add(R.id.realTabContent, fragment);
instead of replacing your fragment.
Understand the difference between replace and add. This will solve your problem.
Replace : it will replace the original fragment and re-create the view when you come back
Add : it will just add a new fragment to stack.
Hope this will help someone who is facing the same problem...
I don't think prevent calling onCreateView is a good idea, beside if the function is not called, there will be exception, so NO, you shouldn't. Instead of doing that, I suggest you move your "listview created and new fetches new server data" into another place where you can call explicitly (when you want, where you want, onCreate() is a good place), don't put it in onCreateView(). Hope this helps.
You should cache your data objects apart from view variables as their references needs to be updated if you are fetching any data from server and don't want to make a call again then use branching to branch out that code.
Create an init() method where you do all initialization and server calls and logically branch out call to init() method whenever you don't want to call init().
Alright. My first question here. And I already found some solution, but honestly do not really get the stuff that happens in the background. So perhaps there’s someone who could clear up this stuff a little bit. After days of debugging I’m just glad that it works... and hope I did not make some serious error. So let’s have a look.
I got some Main-Activity. Just a FragmentActivity extending JFeinstein’s SlidingFragmentActivity. Further I decided to go the fragment-way and just put any content (list-fragment, article-fragment, …) as a fragment into a container (to right of the sliding-menu); my main-container. So far, so good.
One essential fragment is my article-fragment. A ViewPager (with a FragmentStatePagerAdapter) - containing some pages with text and perhaps another list-fragment. Still no problem so far, until I decide to rotate the device. And to be more precise, rotating the device works too as long as I do not decide to update my article-fragment.
I understood (correct me if I am wrong) that Android handles the fragments state on its own when rotating the device. And it seems to be everything fine just until I want to reload/update its content.
Ok let’s dig deeper into that.
On first start I got some empty main-container. Then I am loading my article-fragment for the first time. Just getting the SupportFragmentAdapter, creating my ArticleFragment and replace the main-container with the newly created fragment - tagged. No rocket-science - just a simple transaction:
ViewPagerFragment pagerFragment = (ViewPagerFragment)
getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT_ARTICLE);
if(pagerFragment != null){
if(pagerFragment.isResumed()){
pagerFragment.triggerReload();
}
} else {
pagerFragment = new ViewPagerFragment();
FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.replace(R.id.id_main_root_frame, pagerFragment, TAG_FRAGMENT_ARTICLE);
t.commitAllowingStateLoss();
}
To avoid creating a fragment each time I reload my content, I’m trying to fetch the fragment before the transaction and - if it is found and resumed - trigger some reload on the existing fragment.
Now I rotate my device in this state. To avoid messing with the fragment state I left onSaveInstanceState() inside the fragment untouched. So I guess the fragment is just destroyed and recreated. And everything still works so far. But I think this part has something of a black box.
After that - normal startup, creating fragment and put into main-container, rotating device - I trigger some update. But instead of finding the old (recreated) fragment by tag, nothings found and a new fragment is created and inserted. At least tried to be inserted, because this is where I got the following exception:
java.lang.IllegalStateException: Activity has been destroyed
To be precise, I get the above exception when finish my transaction with a commitAllowingStateLoss(). When I just commit() the transaction I get the following exception:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
So that’s where the error comes up. And after ages of debugging and searching I found some hint on this question/answer to get the SupportFragmentManager on a WeakReference of my MainActivity. And what should I say. Since I implemented that, it works. I had to change my update-process a bit, but it works. But leaves some questions ...
The behaviour seems to be similiar. First creation works perfect. Reload just the same - fragment is found by tag. After rotation, article is still shown. And when I reload the fragment with that state it is not found by tag so a new one is created, but the commit()-request does not throw an exception. A look inside the debugger shows that the WeakReference is some other instance (other id), than the one(this) all of this takes place in. And thats where I lose the plot. ..
If some of you could give me some hints, would be great!
Thanks in advance!
try this:
commitAllowingStateLoss(); instead commit();