Many developers around the world faces the problem while using fragments when specially you are working with backstack. Let’s take an example when you have a Home fragment and display some information and another Fragment has ability to update, when you open Update fragment on top of it and putted HomeFragment to back stack, Your Next fragment performs some update tasks with apis now when you will press back button and your HomeFragment will be popped from backstack this will contains Old Information, but now you want to make api call to reload updated information.
There can be some more complex cases where you need to mark more than one or specific fragment in backstack.
I have already faced such issues in my production app, so i have build some basic and functionality to solve this.
Sharing with you the workaround
1. Create a MainActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package com.codezlab.reloadbackfragment.activities; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.codezlab.reloadbackfragment.R; import com.codezlab.reloadbackfragment.fragments.HomeFragment; import com.codezlab.reloadbackfragment.fragments.UpdateFragment; public class MainActivity extends AppCompatActivity implements HomeFragment.OnFragmentInteractionListener, UpdateFragment.OnFragmentInteractionListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initWithHomeFragment(); } private void initWithHomeFragment() { String fragmentTag = HomeFragment.class.getSimpleName(); Fragment fragment = HomeFragment.newInstance(null, null); FragmentTransaction localFragmentTransaction = getSupportFragmentManager().beginTransaction(); localFragmentTransaction.replace(R.id.fragmentContainer, fragment, fragmentTag).addToBackStack(fragmentTag).commit(); } @Override public void navigateToUpdateFragment() { String fragmentTag = UpdateFragment.class.getSimpleName(); UpdateFragment fragment = UpdateFragment.newInstance(); FragmentTransaction localFragmentTransaction = getSupportFragmentManager().beginTransaction(); localFragmentTransaction.replace(R.id.fragmentContainer, fragment, fragmentTag).addToBackStack(fragmentTag).commit(); } } |
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent" tools:context=".activities.MainActivity"> <FrameLayout android:id="@+id/fragmentContainer" android:layout_width="match_parent" android:layout_height="match_parent"> </FrameLayout> </LinearLayout> |
1. Create class BaseFragment.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package com.codezlab.reloadbackfragment.fragments; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; public class BaseFragment extends Fragment { private boolean reloadRequired = false; public boolean isReloadRequired() { return reloadRequired; } public void setReloadRequired(boolean reloadRequired) { this.reloadRequired = reloadRequired; } protected final boolean markFragmentForReloading(String tag) { boolean marked = false; if (tag == null) return marked; FragmentManager fragmentManager = getFragmentManager(); if (fragmentManager != null) { Fragment fragment = fragmentManager.findFragmentByTag(tag); if (fragment instanceof BaseFragment) { ((BaseFragment) fragment).setReloadRequired(true); marked = true; } } return marked; } } |
3. Create HomeFragment.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
package com.codezlab.reloadbackfragment.fragments; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.Toast; import com.codezlab.reloadbackfragment.R; /** * A simple {@link Fragment} subclass. * Activities that contain this fragment must implement the * {@link HomeFragment.OnFragmentInteractionListener} interface * to handle interaction events. * Use the {@link HomeFragment#newInstance} factory method to * create an instance of this fragment. */ public class HomeFragment extends BaseFragment { // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; private String mParam1; private String mParam2; private Button button; private OnFragmentInteractionListener mListener; public HomeFragment() { // Required empty public constructor } /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param param1 Parameter 1. * @param param2 Parameter 2. * @return A new instance of fragment HomeFragment. */ public static HomeFragment newInstance(String param1, String param2) { HomeFragment fragment = new HomeFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_home, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); button = view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mListener != null) mListener.navigateToUpdateFragment(); } }); } @Override public void onDestroyView() { button.setOnClickListener(null); super.onDestroyView(); } @Override public void onResume() { super.onResume(); /* check if fragment is marked for reloading */ if (isReloadRequired()) { /*un-mark to prevent reloading again*/ setReloadRequired(false); Toast.makeText(getActivity(), "You can call api to update your data", Toast.LENGTH_SHORT).show(); } } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * <p> * See the Android Training lesson <a href= * "http://developer.android.com/training/basics/fragments/communicating.html" * >Communicating with Other Fragments</a> for more information. */ public interface OnFragmentInteractionListener { public void navigateToUpdateFragment(); } } |
4. Create UpdateFragment.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
package com.codezlab.reloadbackfragment.fragments; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import com.codezlab.reloadbackfragment.R; /** * A simple {@link Fragment} subclass. * Activities that contain this fragment must implement the * {@link UpdateFragment.OnFragmentInteractionListener} interface * to handle interaction events. * Use the {@link UpdateFragment#newInstance} factory method to * create an instance of this fragment. */ public class UpdateFragment extends BaseFragment { private OnFragmentInteractionListener mListener; private Button button; public UpdateFragment() { // Required empty public constructor } /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @return A new instance of fragment UpdateFragment. */ public static UpdateFragment newInstance() { UpdateFragment fragment = new UpdateFragment(); Bundle args = new Bundle(); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_update, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); button = view.findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /*supply TagName of the fragment which is added to back stack */ markFragmentForReloading(HomeFragment.class.getSimpleName()); } }); } @Override public void onDestroyView() { button.setOnClickListener(null); super.onDestroyView(); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof OnFragmentInteractionListener) { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * <p> * See the Android Training lesson <a href= * "http://developer.android.com/training/basics/fragments/communicating.html" * >Communicating with Other Fragments</a> for more information. */ public interface OnFragmentInteractionListener { } } |
After building app with above code, you will see HomeFragment has a button to open next UpdateFragment.
Click OpenNextFragment button it will take to UpdateFragment and put current fragment in backstack.
1 2 3 4 |
String fragmentTag = UpdateFragment.class.getSimpleName(); UpdateFragment fragment = UpdateFragment.newInstance(); FragmentTransaction localFragmentTransaction = getSupportFragmentManager().beginTransaction(); localFragmentTransaction.replace(R.id.fragmentContainer, fragment, fragmentTag).addToBackStack(fragmentTag).commit(); |
I have added fragment in back stack with TagName, so that we could access by its tag.
You can see both Fragments extends BaseFragment class, having function to mark previous fragment for reloading by supplying TagName of the fragment.
I will put complete project code to download shortly, till the time enjoy reading and implementing it.
3 Comments
AffiliateLabz
Great content! Super high-quality! Keep it up! 🙂
erotik izle
This is my first time visit at here and i am really pleassant to read all at one place. Neely Fraser Borszcz
erotik izle
Really enjoyed this blog post. Much thanks again. Want more. Maire Duffie Fronnia