Fragment artificial backstack - android

I'm trying to create artificial backstack after opening notification from notification bar.
Workflow after opening notification:
After clicking on notification Intent which opens MainActivity is fired.
After opening MainActivity I check if(getArguments != null). If it's not null I open notifications fragment and pass received notification id.
If notification if(id != -1) I open Notification fragment.
The problem is that after clicking back button I go back straight into MainActivity window skipping Notifications fragment.
I open Notifications fragment like that:
Fragment frag = new NotificationFragment();
frag.setArguments(bundle);
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, NotificationsFragment.getInstance(null, id)).commit();
I open Notification fragment like this:
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
NotificationFragment notificationFragment = new NotificationFragment();
Bundle bundle = new Bundle();
bundle.putInt("id", getArguments().getInt("id"));
notificationFragment.setArguments(bundle);
ft.add(R.id.container, notificationFragment).addToBackStack(null).commit();
R.id.container is FrameLayout used sor showing fragments.
I'm using Support librrary.
I read that FragmentTransaction.replace() deletes all existing fragments and adds new one. And FragmentTransaction.add() adds them to activity state.
Please someone correct me what I'm doing wrong and show me right way.

Change this
Fragment frag = new NotificationFragment();
frag.setArguments(bundle);
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, NotificationsFragment.getInstance(null, id)).commit();
to
Fragment frag = new NotificationFragment();
frag.setArguments(bundle);
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, NotificationsFragment.getInstance(null, id)).addToBackStack(null).commit();
Basically, you are not adding Notifications Fragment to backstack, that's why when clicking back, MainActivity comes up.

Related

Fragment Save State

I've read a lot about save states and fragments, but I can't wrap my head around it.
I have a fragment that is loaded when the user signs in. The user can then choose from a variety of categories, which will replace the current fragment with a new one. In this new fragment, the user can click items in a GridView which will cause a check to appear.
When I press the back button, how would I go about saving the clicked items? onSavedInstanceState is never called, and it seems like my fragment is being created all over again when I try to navigate back.
Some code:
When the user first enters the app
// creates the home fragment
Fragment homeFragment = new HomeFragment();
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.content_frame, homeFragment);
fragmentTransaction.commit();
When the user clicks on a category
Bundle bundle = new Bundle();
bundle.putSerializable("subCategory", subCategory);
Fragment ingredientsFragment = new IngredientsFragment();
ingredientsFragment.setArguments(bundle);
FragmentTransaction fragmentTransaction =
getActivity().getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.content_frame, ingredientsFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
When you move From HomeFragment To IngredientsFragment you are replacing 1 fragment by another (HomeFragment By IngredientsFragment) so when you press back from IngredientsFragment then It will remove IngredientsFragment from stack also and HomeFragment is already removed and this is expected behavior.
What you can do is When you invoke IngredientsFragment Fragment then "add" it not replace and when user press back then remove IngredientsFragment from stack.

How to reopen a fragment with saved instance from another fragment?

I have 1 activity with multiple fragments. These fragments call each other, for example fragment a calls fragment b:
Fragment a:
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, new FragmentB());
ft.commit();
Where OrderAddFragment is fragment b.
Now, let's say a user has filled in multiple inputs in fragment a and continues to fragment b but than he realises he made a mistake in fragment a and needs to go back to correct this mistake.
How could I reopen fragment a with the saved instance state instead of creating a new instance?
The back function in fragment b uses following code to reopen fragment a:
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, new FragmentA());
ft.commit();
FragmentTransaction.addToBackStack() might solve your problem.

Detecting when a fragment is on top again (has focus)

In my app, my activity has a container with a fragment. When a button in that fragment is clicked, I add a new fragment to the container and add the previous fragment to the backstack.
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.primary_fragment_container, homeFragmentHandler);
fragmentTransaction.addToBackStack(folderId.toString());
fragmentTransaction.commit();
The result is that pressing back closes the top fragment and returns me to the previous fragment, which is exactly how I want it. HOWEVER there are certain elements on the fragment that should be refreshed at this point. When the user clicks back and is returned to the previous fragment, how do I know to refresh the data within that fragment? is there a method such as onResume() for this scenario?
You have to proper add fragments to backstack:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
MyFragment fragment = new MyFragment ();
transaction.replace(R.id.primary_fragment_container, fragment).addToBackStack(null).commit();
Fragment homeFragmentHandler= new Fragment();
Bundle bundle = new Bundle();
//replace this line below wth something convinient
bundle.putInt("key", value);
fragment.setArguments(bundle);
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.primary_fragment_container, homeFragmentHandler);
fragmentTransaction.addToBackStack(folderId.toString());
fragmentTransaction.commit();
This will send data regarding which fragment/ activity caused the previous fragment to load. Now in its onCreate add this code to check the data in the bundle
//In the onCreate of the original fragment
Bundle bundle = this.getArguments();
if(bundle.getInt(key, defaultValue)!=null{
int myInt = bundle.getInt(key, defaultValue);
// Load the data that needs to be refreshed when original fragment is loaded from the second one
}
No else statement is needed. If the fragment is made from any other activity/ fragment then the bundle.getInt will return null and hence that code inside the statement wont be executed.

Application not Result when user back from fragment?

I am working on android application .There are 4 tab on Home screen . there are multiple fragment under each tab.I am moving from fragment to second fragment and back on first fragment . when i again moves on second fragment . it does not show any data which i am fetching from web service.It is showing on progress dialog.what may reasons .
I am switching fragment like this.
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
FragmentName llf = new FragmentName();
ft.replace(R.id.container_framelayout, llf);
ft.addToBackStack(null);
ft.commit();
I don't know if it's related to your problem but when you create a fragment from the same class multiple times, you shouldn't do
FragmentName llf = new FragmentName();
You should do something like that :
FragmentName llf = FragmentName.newInstance();
And in FragmentName.class :
public static FragmentName newInstance(){
return new FragmentName();
}
This way, a new Fragment will be made and you won't have any duplicated or "shared" fragment. More information are available here : Best practice for instantiating a new Android Fragment

How to get Data from current fragment to other fragment?

I am using Fragment for my current application. Here I have one Fragment FA and I am navigating to the other Fragment FB and I have added FA to the backstack as I want to come to FA fragment on some event to be done in FB fragment. I have a done button in the fragment FB. On Click of that button I need to do two things in the fragment FB which are as follows :-
(a). I need to finish the current fragment FB.
(b). Secondly, I need to pass some data from FB to already existing Fragment FA as I have added it to backstack.
I have just started using Fragments and don't know much about them and I want to sort out this problem.Can anyone suggest something for this, any Help would be appreciable.
Thanks in Advance.
You can pass data from one fragment to another something like below.
Fragment fragment;
fragment = new SingleImage();
Bundle bundle = new Bundle();
bundle.putString("img",actorsList.get(position).getImage());
bundle.putString("desc",actorsList.get(position).getDesc());
fragment.setArguments(bundle);
getActivity().getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).addToBackStack( "tag" ).commit();
means you can add arguments with fragment to pass to another.
and you can get that data in another fragment using below code
Bundle bundle = this.getArguments();
if(bundle != null)
{
tvdesc.setText(bundle.getString("desc"));
img_url= bundle.getString("img");
}
Since you want only one back stack entry per Fragment, make the back state name the Fragment's class name (via getClass().getName()). Then when replacing a Fragment, use the popBackStackImmediate() method. If it returns true, it means there is an instance of the Fragment in the back stack. If not, actually execute the Fragment replacement logic.
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}

Categories

Resources