134

In an android application I'm loading data from a Db into a TableView inside a Fragment. But when I reload the Fragment it displays the previous data. Can I repopulate the Fragment with current data instead of previous data?

Bugs Happen
  • 2,169
  • 4
  • 33
  • 59
Samantha Withanage
  • 3,811
  • 10
  • 30
  • 59
  • show us some code please. Where do you load your data, where do you start your fragment, where do you store your values? – A.S. Dec 20 '13 at 11:12
  • This should solve your porly described problem: http://stackoverflow.com/questions/6503189/fragments-onresume-from-back-stack – Benjamin W. Dec 20 '13 at 11:14
  • please provide more info-code snippet – nikvs Dec 20 '13 at 11:15
  • Try to use Swipe-to-Refresh To Your App see this http://stackoverflow.com/questions/41469040/fragment-refresh/41470603#41470603 – Imtiaz Mamun Jan 04 '17 at 18:18

22 Answers22

225

I think you want to refresh the fragment contents upon db update

If so, detach the fragment and reattach it

// Reload current fragment
Fragment frg = null;
frg = getSupportFragmentManager().findFragmentByTag("Your_Fragment_TAG");
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();

Your_Fragment_TAG is the name you gave your fragment when you created it

This code is for support library.

If you're not supporting older devices, just use getFragmentManager instead of getSupportFragmentManager

[EDIT]

This method requires the Fragment to have a tag.
In case you don't have it, then @Hammer's method is what you need.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • 3
    This gives following error - java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=3, data=null} to activity {xont.virtusel.v4.controller/xont.virtusel.v4.controller.sale.InvocieBrandActivity}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState – Samantha Withanage Dec 20 '13 at 11:31
  • I call this @ onActivityResult. – Samantha Withanage Dec 20 '13 at 11:35
  • Well, does it make sense to call it in onActivityResult? It seems that your intent is null (you see: data=null). I do it like: I update my db and after I detach/reattach my fragment. – Phantômaxx Dec 20 '13 at 11:40
  • Cannot find a place to use this. Everywhere it throws exception. Some advice, please? Thanks. – statosdotcom Jul 05 '16 at 16:21
  • `Everywhere it throws exception`... isn't this a bit vague? You could make a new question, including all the needed details, to have a chance to get a good answer. – Phantômaxx Jul 08 '16 at 14:50
  • 1
    @Elizabeth make sure your Fragment has a tag properly set – Phantômaxx Oct 21 '16 at 07:17
  • i used id like frg = getFragmentManager().findFragmentById(R.id.table_fragment_container); – Elizabeth Oct 21 '16 at 07:25
  • Then, you used the @Hammer method. – Phantômaxx Oct 21 '16 at 07:45
  • What if I want to do the same as above from Activity? Also, I never gave my Fragment a tag... – Si8 Oct 26 '16 at 23:01
  • @Si8 `What if I want to do the same as above from Activity?` Yes, you're supposed to. `I never gave my Fragment a tag` Then Hammer's answer will do for you. – Phantômaxx Oct 27 '16 at 07:33
  • 1
    @Rotwang Thanks for your reply I just took a shortcut rather than do the long code but that helped paved the way :) – Si8 Oct 27 '16 at 11:07
  • 1
    This solution is not working any more in the new version of support-v4-library (25.1.0). Explanation here : http://stackoverflow.com/questions/41270858/refresh-fragment-not-working-any-more – Brahim Bouaboud Dec 21 '16 at 20:22
  • @RajeshNasit You can explicitly clear it by adding something like `yourEditText.setText("");` – Phantômaxx Jun 16 '17 at 08:18
  • I know it but my case is https://stackoverflow.com/questions/44581051/reloading-fragment-edittexts-text-not-cleared – Rajesh N Jun 16 '17 at 08:56
  • @RajeshNasit Manually reset your Views in the Fragment's `onAttach()` method. – Phantômaxx Jun 16 '17 at 09:31
  • 1
    Warning: this trick works on Oreo only if you are using Support Fragments! – racs Mar 10 '18 at 07:15
  • This answer is outdated. With the new navigation system, we can navigate to the same page : ``Navigation.findNavController(requireActivity(), R.id.fragment_container_view).navigate(R.id.selfFragment)`` – Foxhunt Oct 30 '21 at 20:55
  • @Phantômaxx Thank you. This answer helped. However, for `androidx.navigation:navigation-fragment-ktx` version `2.5.3`, Android Studio's lint suggests separating the `detach()` and `attach()` method calls onto different FragmentTransaction instances. – Mwanagenzi Aug 17 '23 at 11:30
  • @Mwanagenzi Well, try the suggested methods by Android Studio. This answer of mine is 10 years old, and there are probably better ways to manage the situation, nowadays. – Phantômaxx Aug 24 '23 at 12:05
160

This will refresh current fragment :

FragmentTransaction ft = getFragmentManager().beginTransaction();
if (Build.VERSION.SDK_INT >= 26) {
   ft.setReorderingAllowed(false);
}
ft.detach(this).attach(this).commit();
UdayaLakmal
  • 4,035
  • 4
  • 29
  • 40
Mbengue Assane
  • 2,855
  • 1
  • 17
  • 14
37

In case you do not have the fragment tag, the following code works well for me.

 Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
    
   if (currentFragment instanceof "NAME OF YOUR FRAGMENT CLASS") {
       FragmentTransaction fragTransaction =   (getActivity()).getFragmentManager().beginTransaction();
       fragTransaction.detach(currentFragment);
       fragTransaction.attach(currentFragment);
       fragTransaction.commit();
    }
Jamil Hasnine Tamim
  • 4,389
  • 27
  • 43
Hammer
  • 8,538
  • 12
  • 44
  • 75
25

To refresh the fragment accepted answer will not work on Nougat and above version. To make it work on all os you can do following.

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        fragmentManager.beginTransaction().detach(this).commitNow();
        fragmentManager.beginTransaction().attach(this).commitNow();
    } else {
        fragmentManager.beginTransaction().detach(this).attach(this).commit();
    }
Sachin Jagtap
  • 527
  • 6
  • 16
12

you can refresh your fragment when it is visible to user, just add this code into your Fragment this will refresh your fragment when it is visible.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // Refresh your fragment here          
  getFragmentManager().beginTransaction().detach(this).attach(this).commit();
        Log.i("IsRefresh", "Yes");
    }
}
7

If you are using NavController, try this (kotlin):

val navController = findNavController()
navController.run {
    popBackStack()
    navigate(R.id.yourFragment)
}
J.G.
  • 91
  • 2
  • 5
6

You cannot reload the fragment while it is attached to an Activity, where you get "Fragment Already Added" exception.

So the fragment has to be first detached from its activity and then attached. All can be done using the fluent api in one line:

getFragmentManager().beginTransaction().detach(this).attach(this).commit();

Update: This is to incorporate the changes made to API 26 and above:

FragmentTransaction transaction = mActivity.getFragmentManager()
                        .beginTransaction();
                if (Build.VERSION.SDK_INT >= 26) {
                    transaction.setReorderingAllowed(false);
                }
                transaction.detach(this).attach
                        (this).commit();

For more description of the update please see https://stackoverflow.com/a/51327440/4514796

Ali Nem
  • 5,252
  • 1
  • 42
  • 41
  • 2
    Please provide your answer with clear descriptions. Don't write the code, give the explanation about the code which you have shared, so that others can also understand and it will be helpful. I request you to read the FAQ Section in-order to use Stack Overflow in an effective manner. – Sankar Ganesh PMP Sep 27 '17 at 13:41
6

In case you are using Navigation Components
You can use navigate(this_fragment_id) to navigate to this fragment but in a new instance. Also you have to pop the backstack before to remove the actual fragment.

Kotlin

val navController: NavController = 
     requireActivity().findNavController(R.id.navHostFragment)
navController.run {
            popBackStack()
            navigate(R.id.this_fragment_id)
        }

Java

NavController navController = 
    requireActivity().findNavController(R.id.navHostFragment);
navController.popBackStack();
navController.navigate(R.id.this_fragment_id);
Martin Olariaga
  • 379
  • 4
  • 4
3
   MyFragment fragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
        getSupportFragmentManager().beginTransaction().detach(fragment).attach(fragment).commit();

this will only work if u use FragmentManager to initialize the fragment. If u have it as a <fragment ... /> in XML, it won't call the onCreateView again. Wasted my 30 minutes to figure this out.

Irshu
  • 8,248
  • 8
  • 53
  • 65
1

Here what i did and it worked for me i use firebase and when user is logIn i wanted to refresh current Fragment first you will need to requer context from activity because fragment dont have a way to get context unless you set it from Activity or context here is the code i used and worked in kotlin language i think you could use the same in java class

   override fun setUserVisibleHint(isVisibleToUser: Boolean) {
    super.setUserVisibleHint(isVisibleToUser)
    val context = requireActivity()
    if (auth.currentUser != null) {
        if (isVisibleToUser){
            context.supportFragmentManager.beginTransaction().detach(this).attach(this).commit()
        }
    }

}
1
getActivity().getSupportFragmentManager().beginTransaction().replace(GeneralInfo.this.getId(), new GeneralInfo()).commit();

GeneralInfo it's my Fragment class GeneralInfo.java

I put it as a method in the fragment class:

public void Reload(){
    getActivity().getSupportFragmentManager().beginTransaction().replace(LogActivity.this.getId(), new LogActivity()).commit();
}
MrCabrac
  • 61
  • 3
0

Use a ContentProvider and load you data using a 'CursorLoader'. With this architecture your data will be automatically reloaded on database changes. Use third-party frameworks for your ContentProvider - you don't really want to implement it by yourself...

artkoenig
  • 7,117
  • 2
  • 40
  • 61
0

I had the same issue but none of the above worked for mine. either there was a backstack problem (after loading when user pressed back it would to go the same fragment again) or it didnt call the onCreaetView

finally i did this:

public void transactFragment(Fragment fragment, boolean reload) {
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
    if (reload) {
        getSupportFragmentManager().popBackStack();
    }
    transaction.replace(R.id.main_activity_frame_layout, fragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

good point is you dont need the tag or id of the fragment either. if you want to reload

Emad
  • 465
  • 5
  • 9
0

Make use of onResume method... both on the fragment activity and the activity holding the fragment.

Mwangi Gituathi
  • 305
  • 2
  • 10
0

For example with TabLayout: just implement OnTabSelectedListener. To reload the page, you may use implement SwipeRefreshLayout.OnRefreshListener i.e. public class YourFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

the onRefresh() method will be @Override from the interface i.e.:

@Override
public void onRefresh() {
 loadData();
}

Here's the layout:

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tablayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryLighter"
    app:tabGravity="fill"
    app:tabIndicatorColor="@color/white"
    app:tabMode="fixed"
    app:tabSelectedTextColor="@color/colorTextPrimary"
    app:tabTextColor="@color/colorTextDisable" />

Code in your activity

TabLayout tabLayout = (TabLayout) findViewById(R.id.tablayout); tabLayout.setupWithViewPager(viewPager);

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            if (tab.getPosition() == 0) {
                yourFragment1.onRefresh();
            } else if (tab.getPosition() == 1) {
                yourFragment2.onRefresh();
            }
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
JavaEE guy
  • 174
  • 1
  • 4
0
// Reload current fragment
Fragment frag = new Order();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_home, frag).commit();
  • 2
    This question was answered nearly seven years ago, and has two answers with more than 100 votes each, alongside thirteen other answers. Several use a similar overall approach—though none use `R.id.fragment_home` specifically. What is the benefit to your approach? Why would someone want to use it over one of the highly-upvoted answers? It's fine to add new answers to old questions, but please edit your answer to provide a summary of _why_ your answer contributes value to this thread. – Jeremy Caney Sep 20 '20 at 21:33
  • 2
    I had tried the above two methods with 100+ votes too but none solved my issue, as the first one is using findFragmentByTag, but in my case that returns a null value, and for the second answer "ft.detach(this)" I wasn't able to use "this" as it always shows red line coz I was using location listener and instead of giving me a fragment this returns a location listener, so the only way I was able to reload my fragment was method in the answer. – programmingWithIzebel Sep 24 '20 at 14:35
0

None of these answers worked for me so I might as well post my solution if anyone still has problems with this. This solution works only if you are using the Navigation component.

Go to your navigation graph and find the fragment you want to refresh. Create an action from that fragment to itself. Now you can call that action inside that fragment like so.

private void refreshFragment(){
    // This method refreshes the fragment
    NavHostFragment.findNavController(FirstFragment.this)
            .navigate(R.id.action_FirstFragment_self);
}
0
Below code reloads the current fragment onClick of button from Parent Activity.

        layoutNews.setOnClickListener(v -> {
             FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
             ft.replace(R.id.fragment_container, fragNews);
             ft.detach(fragNews);
             ft.attach(fragNews);
             ft.commit();
        });
Arwy Shelke
  • 333
  • 1
  • 2
  • 12
0

If you are in a fragment then use:

findNavController().run {
    popBackStack()
    navigate(R.id.your_fragment)
}
JustSightseeing
  • 1,460
  • 3
  • 17
  • 37
0
findNavController().run {
  popBackStack()
  navigate(R.id.nameFragment)
}

you can refresh it easily by using findNavController() in Kotlin

-1

Easiest way

make a public static method containing viewpager.setAdapter

make adapter and viewpager static

public static void refreshFragments(){
        viewPager.setAdapter(adapter);
    }

call anywhere, any activity, any fragment.

MainActivity.refreshFragments();
-2
protected void onResume() {
        super.onResume();
        viewPagerAdapter.notifyDataSetChanged();
    }

Do write viewpagerAdapter.notifyDataSetChanged(); in onResume() in MainActivity. Good Luck :)

IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198