Search code examples
javaandroidandroid-fragmentsandroid-activityandroid-fragmentactivity

Restarting Activity on Specific Fragment, when Using a Separate FragmentPagerAdapter


Background
I have an android app using fragments. I'm using a separate FragmentPagerAdapter (i.e. as a separate class, outside MainActivity).

MainActivity.java

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.MainActivity);

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
    tabLayout.setupWithViewPager(mViewPager);

}

SectionsPagerAdapter.java

public SectionsPagerAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            return new frag1();
        case 1:
            return new frag2();
        case 2:
            return new frag3();
        case 3:
            return new frag4();
        case 4:
            return new frag5();
        default:
            return null;
    }
}

@Override
public int getCount() {
    return 5;
}

@Override
public CharSequence getPageTitle(int position) {
    switch (position) {
        case 0:
            return "Name1";
        case 1:
            return "Name2";
        case 2:
            return "Name3";
        case 3:
            return "Name4";
        case 4:
            return "Name5";
    }
    return null;
}

The Issue
I need to refresh the view of, say, fragment #3 from fragment#2 (the ultimate goal is for changes the user initiates on fragment #2 to be visible as soon as the user proceeds to fragment#3. I have tried to detach/attach fragment #3 itself as soon as it is visible, like this:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        getFragmentManager().beginTransaction().detach(this).attach(this).commit();
    }

Unfortunately, a) this has a penalty in performance, as there is a "stutter" during navigation; b) it doesn't work reliably. Some things (the texts of some buttons) are not refreshed, for some reason I can't figure out.

In any case, I have discovered that the only 100% reliable method for forcing a refresh/redraw is to restart the activity (for example through an onClickListener on a Save button the user needs to press on the previous fragment, #2). But this restarts the Activity on fragment #1

My Question
How can I restart the activity on this specific fragment (#3), considering the fact I'm using a separate FragmentPagerAdapter?

I've studied several other questions/answers, for example this: https://stackoverflow.com/a/36064344
but how can I implement something like this (putting extras on the intent call) when the FragmentPagerAdapter is on a separate class? Alternatively, is there something else I can do to refresh the fragment view?

If you need extra info or code, let me know and I'd be glad to add clarification.

EDIT: I managed to find another solution that so far seems to be working as intended. I added the following code on the onClickListener of the Save button on fragment #2

    frag3 f3 = new frag3();
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragmentContainer, f3);
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.commit();

However, I'm still interested in my original question (how to start an activity on a specific fragment when using a separate FragmentPagerAdapter), so if you have any ideas about that, I'm all ears.


Solution

  • Well, wasn't that simple...
    this.recreate(); not only restarts the activity but it also remembers the fragment position.

    Just in case someone else needs this, when you're working from fragments you need to use it this way:

    • First declare the activity which contains the fragment in question. E.g.

      public class frag1 extends Fragment {
      ...
      Activity mactivity;
      
      @Override
      public void onAttach(Activity MainActivity) {
          super.onAttach(MainActivity);
          mactivity = MainActivity; 
      }
      
    • Then instead of getActivity().recreate(); simply use mactivity.recreate();