Fragment Switching in the same Activity restarts the same Fragment - android

I am working on an application.
Somewhere I want to load a Fragment in an Activity and when a Gridview/Listview item will be clicked on the FirstFragment, I load the SecondFragment
I have added the Fragments the way below:
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.form_creation_view);
Fragment fragment = new FirstFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.form_view, fragment).commit();
}
Second Fragment:
Fragment fragment = new SecondFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.addToBackStack(null);
fragmentTransaction.replace(R.id.form_view, fragment).commit();
OnBackPress of MainActivity.java :
#Override
public void onBackPressed() {
if(getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
So, when I press the BackButton on the Mainactivity when SecondFragment is loaded, it switches to the FirstFragment, but it calls the onCreateView() method of the FirstFragment again.
The FirstFragment has a Recyclerview inside and I send an API request in the OnCreateView() method to the server in order to load the data into this Recyclerview.
Now when I come back again to this Fragment from the SecondFragment, I want the it so that the request should not be executed and the data should be populated into the RecyclerView.
How can I achieve this?
Can anyone please help me here?

in your onCreateView, you should do a check like this:
if(mList.size() == 0){
//make api call
}else{
//set recyclerView adapter
}
This way, when you come back from the SecondFragment you can repopulate the RecyclerView.
You should also consider saving this list on onSaveInstanceState

Related

How to fix fragments backstack issues in android

Hi everyone i have an issue in my code , i am using one main activity and two fragments (mainfragment,mainsubfragment) the application is about getting data from json parser and displaying it in mainfragment and when you click on it , it should display some data in mainsubfragment.The problem is that when i click on one of the display item in mainfragment its replace this fragment with mainsubfragment with key upon which it should get some more data from another json parser but instead it shows nothing and when i pressed back to mainfragment nothing display there as well.A quick help will be appreciated...
Create a singleton named NavigationHandler and add the below functions to it:
Function to open MainFragment:
public void openMainFragment(FragmentManager fragmentManager, MainFragment fragment){
String backStackName = fragment.getClass().getSimpleName();
fragmentManager.beginTransaction()
.replace(R.id.fl_main_container, fragment)
.addToBackStack(backStackName)
.commit();
}
Function to open SubFragment:
public void openSubFragment(FragmentManager fragmentManager, SubFragment fragment){
String backStackName = fragment.getClass().getSimpleName();
fragmentManager.popBackStackImmediate(backStackName, POP_BACK_STACK_INCLUSIVE);
fragmentManager.beginTransaction()
.replace(R.id.fl_main_container, fragment)
.addToBackStack(backStackName)
.commit();
}
For backpress:
public void navigateBackBy(AppCompatActivity activity, int numOfFragments){
if(mFragmentManager.getBackStackEntryCount()==1){
activity.finish();
}
else {
int i;
for (i = 0; i < numOfFragments; i++) {
mFragmentManager.popBackStackImmediate();
}
}
}
In your Activity:
Call openMainFragment(...) to open the MainFragment with the list.
While calling your adapter constructor pass FragmentManager as a parameter.
Override onBackPressed() & add call navigateBackBy(this, 1);. This method is useful to go back by any no. of fragments.
Inside your adapter:
On click of an item call openSubFragment(...).
Welcome to stack over flow
According to you , you are using two fragment
1.mainfragment >> don't add to addToBackStack
2.mainsubfragment>> add to addToBackStack
for fragmetn1 call like as
Fragment fragment = new mainfragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
for second fragment2
fragment = new mainsubfragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().addToBackStack(null).replace(R.id.content_frame, fragment).commit();
then it will be work and on back press also will be work

Memory leak on fragment transaction

I have two fragments one list and one detail fragment. On list item click I a hiding list fragment and adding detail fragment on back press detail fragment is popped automatically I am just calling super.onBackPressed() but issue is it is creating so many references of detail fragments resulting is memory leaks
Following is my code
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.hide(this);
ft.add(containerId, detailFragment, "detail");
ft.addToBackStack("detail");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
I don't want to view to be recreated view when user press back button on detail fragment thats why I used above approach. Also with current implementation when I press back button recylerview scroll possition and other data I don't have to save
My Activity has only following code it inflates list fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.FragmentContainer1, ListFragment.newInstance(), TAG).commit();
}
I think what you are doing wrong is that you are adding fragments each time to the container again and again by calling add method:
In your case you should use replace method and add your list fragment to the backstack. Here's how you should start your detail fragment:
FragmentManager fm = getFragmentManager();
fm.beginTransaction()
.replace(R.id.container, new DetailFragment())
.addToBackstack(null)
.commit();
To get back to your list fragment, which is in the back stack, just call:
fm.popBackStack();
EDIT:
Try this to show your list fragment:
protected void displayListFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (listFragment.isAdded()) {
ft.show(listFragment);
} else {
ft.add(R.id.flContainer, listFragment, "ListFragment");
}
if (detailFragment.isAdded()) {
ft.remove(detailFragment);
}
ft.commit();
}
And this to show your detail fragment:
protected void displayDetailFragment() {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (listFragment.isAdded()) {
ft.hide(listFragment);
}
if (!detailFragment.isAdded()) {
ft.add(R.id.flContainer, detailFragment, "DetailFragment");
}
ft.commit();
}

How go back from Fragment A to Fragment B?

I need to go from FragmentA to FragmentB (i'm using navigationdrawer)
I create this method in FragmentB:
public void onBackPressed(){
FragmentManager fm = getActivity().getFragmentManager();
fm.popBackStackImmediate();
}
but they don't work, how can i implement this method?
When you add your fragment, you also have to add it to your fragment's backstack.
FragmentTransaction ft = getSupportFragmentManager.beginTransaction();
ft.replace(R.id.content, fragment, backStateName);
ft.addToBackStack(backStateName);
ft.commit();
(here R.id.content is your fragment container in your activity)
Then you have to override onBackPressed method in your activity that contains your fragments.
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
getSupportFragmentManager().popBackStack();
}
}
if you want to customize your onBackPressed then you can check for your currently visible fragment in your activity and create a callback for performing action for that particular fragment.
example -
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.content);
if (fragment instanceof FragmentB) {
((FragmentB) fragment).onBackPressed();
// getSupportFragmentManager().popBackStack();
}
}
now you can add getSupportFragmentManager().popBackStack(); in your Fragment's onBackPressed() method.
This code should be inside Activity holding both fragments.
Be sure, that you add (not replace) the fragment to back stack, by calling:
android.app.FragmentTransaction#add(int, android.app.Fragment, java.lang.String)
android.app.FragmentTransaction#addToBackStack
android.app.FragmentTransaction#commit
or their equivalent from support library
For going to the one fragment to another I am calling the Activity's method from Fragment so that the Activity's method has access to that view which is holding fragment and it can switch easily.
like this in my Fragment
((MainActivity) getActivity()).TransitionFromItemToCategory();
And in the fragment Like this
public void TransitionFromItemToCategory(){
FoodCategoryFragment FCM = new FoodCategoryFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, FCM);
ft.commit();
}

Fragment Master-Details with saved State

In an activity there is a fragment that contains a list of objects. This fragment should be replaced by another fragment that contains details of a list item. When the detail fragment is active and the back button is pressed then the listfragment should be resumed.
my code:
#Override
public void onBackPressed() {
if (detailsFragment.isVisible())
{
goToListFragment();
}
}
}
public void goToListFragment() {
String backStateName = listFragment.getClass().getName();
FragmentManager fm = getSupportFragmentManager();
boolean fragmentPopped = fm.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.main_fragment_container, listFragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}
public void goToDetailsFragment(String foodAsJSON) {
String backStateName = detailsFragment.getClass().getName();
getSupportFragmentManager().beginTransaction()
.replace(R.id.main_fragment_container, detailsFragment)
.addToBackStack(backStateName)
.commit();
}
what I observe:
listfragment: onPause()
<back pressed in details view>
listfragment: oncreateView()
listfragment: onResume()
So, when the back button is pressed I would expect that only the onResume function is called. Actually that how its described in the fragment lifecycle. But as I have observed the oncreateView() is called too. That causes the fragment to reload completely and that's not the wanted behavior. So, how do I resume the master fragment properly?

android fragment handle back button press not working

I am working fragment, I replaced FragmentA by fragment B.it's working perfect,but when I press back button I can't back Fragment A.
I tried to override onKeyDown method,but I can't override this method in fragment
this is a my source
CategoryViewPager fragment1 = new CategoryViewPager();
FragmentTransaction ft = getSupportFragmentManager()
.beginTransaction().addToBackStack("method");
ft.setCustomAnimations(R.anim.trans_left_in, R.anim.trans_left_out);
ft.replace(R.id.content_frame, fragment1, "fragment2");
ft.commit();
when I use CategoryViewPager and click back button I can't go back(fragment wich i replaced this fragment)
how can I solve my problem?
Call addToBackStack() before you commit the transaction:
getSupportFragmentManager().beginTransaction()
// Add this transaction to the back stack
.addToBackStack()
.commit();
No need to use tag in your case. just use like this
/*
* Add this transaction to the back stack.
* This means that the transaction will be remembered after it is
* committed, and will reverse its operation when later popped off
* the stack.
*/
fragmentTransaction.addToBackStack(null);
It is better to handle back button press through your activity unless your actvity host large number of fragments.When you press back button inside your fragment onBackPressed() method of your activity will be called which can be overridden and handled..So handling back button for fragments can be done in this way..
MainActvity
public static boolean isMainActivityShown ;
public static boolean isFragment1Shown=false ;
public static boolean isFragment2Shown=false ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
isMainActivityShown=true //inside onCreate method put isMainActivityShown true
.
.
.
}
.
.
Fragment currentFragment = new Fragment1();
isMainActivityShown=false; //when moving to fragment1
isFragment1Shown=true;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
#Override
public void onBackPressed() {
if(isMainActivityShown)
{
finish();
}
else if(isFragment1Shown)
{
//write the code to handle back button when you are in Fragment1
}
else if(isFragment2Shown)
{ //When you are in Fragment 2 pressing back button will move to fragment1
Fragment currentFragment = new Fragment1();
isFragment2Shown=false;
isFragment1Shown=true;
FragmentManager frgManager;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
}
}
Fragment1
Fragment currentFragment = new Fragment2();
MainActivity.isFragment1Shown=false;
MainActivity.isFragment2Shown=true;
frgManager = getFragmentManager();
frgManager.beginTransaction().replace(R.id.content_frame, currentFragment)
.commit();
Check this link
Check the addToBackStack(String name) method. This should solve your problem.

Categories

Resources