@Ali's answer is good, yet imagine if you have 5 fragments. This is another way to show/hide your fragments:
// in BaseFragment
public abstract String getTAG();
//in FragmentA, FragmentB and FragmentC
public String getTAG(){
return TAG;
}
//Activity containing the fragments
//android.support.v4.app.Fragment;
private FragmentA fragmentA; //inherited BaseFragment
private FragmentB fragmentB; //inherited BaseFragment
private FragmentC fragmentC; //inherited BaseFragment
private ConcurrentHashMap<String,BaseFragment> mapOfAddedFragments = new ConcurrentHashMap<>();
/**
* Displays fragment A
*/
private void displayFragmentA() {
displayFragment(fragmentA)
}
/**
* Displays fragment B
*/
private void displayFragmentB() {
displayFragment(fragmentB)
}
/**
* Displays fragment C
*/
private void displayFragmentC() {
displayFragment(fragmentC)
}
/**
* Loads a fragment using show a fragment
* @param fragment
*/
private void displayFragment(BaseFragment fragment){
if(!mapOfAddedFragments.containsKey(fragment.getTAG()))
mapOfAddedFragments.put(fragment.getTAG(), fragment);
showFragment(fragment.getTAG(), R.id.containerBody);
}
/**
* Displays a fragment and hides all the other ones
* @param fragmentTag is the tag of the fragment we want to display
*/
private void showFragment(String fragmentTag, @IdRes int containerViewId){
FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
BaseFragment fragment = null;
fragment = mapOfAddedFragments.get(fragmentTag);
if(fragment != null) {
if (fragment.isAdded())
ft.show(fragment);
else { //fragment needs to be added to the frame container
ft.add(containerViewId, fragment, fragment.getTAG());
}
}
else //the chosen fragment doesn't exist
return;
//we hide the other fragments
for (ConcurrentHashMap.Entry<String, BaseFragment> entry : mapOfAddedFragments.entrySet()){
if(!entry.getKey().equals(fragmentTag)){
BaseFragment fragmentTemp = entry.getValue();
// Hide the other fragments
if(fragmentTemp != null)
if(fragmentTemp.isAdded())
ft.hide(fragmentTemp);
}
}
//commit changes
ft.commit();
}
And to instantiate them you can do this in the onCreate() method of your activity:
//don't forget to get the .TAG elsewhere before using them here
//never call them directly
private void instantiateFragments(Bundle inState) {
if (inState != null) {
fragmentA = inState.containsKey(FragmentA.TAG) ?
(FragmentA) getSupportFragmentManager().getFragment(inState, FragmentA.TAG):
FragmentA.newInstance(FragmentA.TAG,"0");
fragmentB = inState.containsKey(FragmentB.TAG) ?
(FragmentB) getSupportFragmentManager().getFragment(inState, FragmentB.TAG):
FragmentB.newInstance(FragmentB.TAG,"1");
fragmentc = inState.containsKey(FragmentC.TAG) ?
(FragmentC) getSupportFragmentManager().getFragment(inState, FragmentC.TAG):
FragmentC.newInstance(FragmentC.TAG,"2");
}
else{
fragmentA = FragmentA.newInstance(FragmentA.TAG,"0");
fragmentB = FragmentB.newInstance(FragmentB.TAG,"1");
fragmentc = FragmentC.newInstance(FragmentC.TAG,"2");
}
}
Edit according to Shujaat Ali Khan's question:
The BaseFragment extends support4 fragment:
public abstract class BaseFragment extends Fragment {
public abstract String getTAG();
//whatever we can add to be inherited
}
FragmentA for example:
public class FragmentA extends BaseFragment {
// Store instance variables
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
public static final String TAG = "FragmentA";
// newInstance constructor for creating fragment with arguments
public static FragmentA newInstance(String param1, String param2) {
FragmentA fragment = new FragmentA();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
// Store instance variables based on arguments passed
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
// Inflate the view for the fragment based on layout XML
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragmentA, container, false);
return view;
}
//other lifecycle methods
@Override
public String getTAG() {
return TAG;
}
}
Finally the R.id.containerBody
is the id of a FrameLayout containing the fragments in the activity containing these fragments.