I have 2 fragments which are called from the action bar of an activity. Both are gridviews, the first one displays applications with a dedicated adapter, and the second one displays a file list with another adapter. My problem is that when I launch a file then when I back to my activity I switch from one fragment to another, when I come back to the previous one, its content disappears. And when I rotate tablet I have the some problem, because my Fragment restart so for this I think that removing fragment give the possibility to create a new Fragment up to date. How can I save and reload data in my fragment.
How can I manage to update the content of the first fragment while coming back from the second one ? And how to remove fragment after the rotation in order to recreate the Action with new Fragment? I asked this questions but I don't have any responses. the code is given below
If your data is just strings or integers, you can make use of shared preferences to store and retrieve data.
Solution to your first problem -how to save fragment state
Use setRetainInstance(true) in you fragments onCreate() *it prevents your fragment from destroying and hence recreating.
Add your fragment to back stack
declare your adapter globally in fragment and resuse it when you get back.
when, you get back to fragment its onCreateView() method will be called directly. hence initialize your adapter in onCreate() method and use it in onCreateView().
Solution to your second problem -how to update fragment content
For this you can use interface. create interface in your second fragment and implement it in your first fragment. prefer this doc for this,
http://www.vogella.com/tutorials/AndroidFragments/article.html#fragments_activitycommunication
Related
Okay I know this has been asked previously but just hear me out !
ISSUE
I want to save state of a fragment and then retrieve it in onCreateView method .
I have a ViewPager in my MainActivity with Four Fragments in it .
I have used viewpager.setOffscreenPageLimit(2) so fragments does not get recreated if am in any of two adjacent fragments but if i am in my first fragment and i go to fourth one then fragment first gets recreated .
and if save it in onSaveInstance inside fragment then that does not get called until host activity's same method is not called , which will not get called if am just swiping between fragments
Answer here also has same problem , it is saving fragments in host activity's onSaveInstance method .So i know how to save fragments state and retrieve it if my host activity gets recreated but what if only fragments gets recreated ?
So How can i save state of a fragment without depending on host activity and then retrieve it in onCreateView method of fragment ?
UPDATE
Just realized how dumb a person can be , data was there all the time i was not just refilling the views with it .
Thanks in advance.
So I currently have an app that has 4 tabs (fragments). They are fragments A,B,C,D, in that order.
Fragment A is the first view opened (along with B because viewPager loads the view before and after the current view).
When I click a button in Fragment A, it sends Data back to MainActivity and then sends that data out to Fragments B and C.
However, this is where the issue comes into play. Since Fragment B was already called, the View isn't updated once I click the button and send the data over, but Fragment C is because the view wasn't called before.
Is there any way that I can remedy this?
You can do it a few ways right.
Just set the data to the fragment and have it update its views
Have all the fragments like B and C register themselves to recieve data from the MainActivity and when MainActivity gets it's data set you tell all the registered receivers of the new data
Recreate the fragment
Use an event bus and tell all subsribers of the new data and MainActivity, Fragment B would get notified of new data. Fragment C would get its data when created by MainActivity
I think this list is pretty endless tbh
The key here is the fragments need to fetch the data from the actvitiy aswell as be updated by the activity. In which case you need to break your UI update behaviour out of onCreateView and into its own updateUI() function. updateUI(MyData) can then be called from onCreateView and also called in a setMyData() on the fragment. Just make sure you check the isAdded flag in setMyData.
This pretty much says it all:
http://developer.android.com/training/basics/fragments/communicating.html
I used a simple fragment communicator that allows the activity to call the fragment, and the same for a fragment to talk to the activity.
You can change the views with the new data based on calling the method from within the activity. The way I do it is set the fragments in the activity then pass them into the page adapter this way I can call the methods within the fragment and implement the fragmentcommunicator interface on the fragments.
You can honestly even avoid the interface if you want, but if you are going to include the same method in all the fragments to talk to them it is easiest.
If you show code, I can show you a quick example.
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().
I have 2 Tabs and 2 Corresponding Fragments. On calling the LAUNCH Activity both Tabs were added and then the first one added will be shown. Thus the first Fragments onCreateView is called the second Fragments ones not.
In my case this is an issue because the first Fragment has to call methods on the second Fragment. Inside the second Fragment there is an Objectreference which will be set by calling the onCreateView in the second Fragment.
Therefore I used following code snippet to solve this
actionBar.setSelectedNavigationItem(1);
actionBar.setSelectedNavigationItem(0);
It works but in my opinion there must be another possibility to solve this issue. Like calling the onCreateView of the second Fragment?
Here is the relevant code snippet. The listener is implemented as in android-dev Sample only with small changes not affecting my issue.
simplexFragment corresponds to the first Fragment
graphicFragment corresponds to the second Fragment
// adds two tabs
actionBar.addTab(actionBar.newTab().setText("Input").setTabListener(new TabListener(null, "input_fragment")));
graphicFragment = new GraphicFragment();
actionBar.addTab(actionBar.newTab().setText("Graphic").setTabListener(new TabListener(graphicFragment, "graphic_fragment")));
simplexFragment.setGraphics(graphicFragment); // sets the internal reference!
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// selects the Tab so the GraphicFragments onCreateView will be called
actionBar.setSelectedNavigationItem(1);
actionBar.setSelectedNavigationItem(0);
Thanks for support.
In my case this is an issue because the first Fragment has to call methods on the second Fragment.
This is not how Fragments are meant to work. The idea is a Fragment should be self-contained and re-usable and one Fragment shouldn't know that another exists (or at least shouldn't rely the existence any other Fragment).
For example, suppose you have 3 Fragments and ActivityA uses FragmentA and FragmentB but you have another Activity (ActivityB) which uses FragmentA and FragmentC. In that case, FragmentA doesn't know what the other Fragment is (B or C) and shouldn't even expect there to be another Fragment at all.
The way to achieve what you want is to use callback methods on the Activity and have it perform the actions on any other Fragments (if they exist). It can do this by either calling public methods on the other Fragments or by passing data in the 'arguments' Bundle when it creates the other Fragments.
I have a ListFragment, which data is loaded by a SimpleCursorLoader(own imlementation; it loads with a curser and does not use URI).
When an item in the list is selected. I either start up a new activity (detail activity) or I show what is selected in the detail fragment next to the ListFragment. Depending on the screen size.
If the detail fragment is added to the ListActivity, I have figured out how to reload the list. I assign an interface to the ListActivity and call it from the detail fragment, when the change is happening. And in the list fragment I reload the list using getLoaderManager().restartLoader(0, null, this);
Now my problem is, if the detail activity is loaded, I don't have access to methods on the ListActivity. I could probably implement some observer pattern. But there must be a best practice for this.
How do you make a ListFragment reload the list, when a detail fragment has changed the data in the database.
Try moving your list creation code to onResume. That way it runs on activity creation and every time you go away from the activity and come back.