Pacemaker
Pacemaker

Reputation: 1117

Refresh/Reload/Re instantiate a Fragment in an android tab system

I have an activity with a viewpager that has 3 tabs and 3 fragments, inside each tab is a fragment. I know that the fragment manager stores the initial instances of the fragments so that if I swipe away from a tab then return to that tab, it is loaded in memory and no updates are applied to it.

I need the opposite to happen, that is: Every time I swipe to a tab, a new instance of the fragment in that tab needs to load so that data will be updated.

I have tried:

  1. detach attach fragment in onTabSelected (nothing happens)
  2. remove add fragment in onTabSelected (nothing happens)
  3. setOffscreenPageLimit(0) (Nothing happens)
  4. refresh function inside each fragment to be called onTabSelected (gives nullPointerException)

I have been struggling with this problem for a week with no progress. I appreciate any help, be it a hint, a comment, a suggestion.

Let me know what code should I post, Thanks.

Upvotes: 12

Views: 29435

Answers (5)

Suganth S
Suganth S

Reputation: 1

I face this issue more than a day, and also i tried with every solutions which said regarding this ,but nothing works out in my case..

considering my case, I have done it in a MVVM architecture, I have a tab fragment, and two child fragments in it...I have to update my fragment, when I switch tabs and when i Swipe a tab... Since at the time of posting, FragmentStatePagerAdapter and FragmentPagerAdapter is deprecated from API 27, so I picked FragmentStateAdapter , and I have found two solutions

  1. Works when I switch tabs, but not on swipe,
  2. Works in both cases of Switch /Swipe of tabs..

Solution Followed by,

Case 1 : I did my viewpager impl same like this from github.. Coming to a refreshing state of switching a tabs below code works for me, but it wont works when you swipe a tabs...

In your TabFragment.kt

fun onViewCreated (...){
         .....
         .....
        viewPager.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback(){
            override fun onPageScrolled(
                position: Int,
                positionOffset: Float,
                positionOffsetPixels: Int
            ) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels)
            }

            override fun onPageSelected(position: Int) {
                super.onPageSelected(position)
            //Whenever switching tabs, call coms here and our respective child 
            //fragment reloads
                adapter.notifyItemChanged(position)
            }

            override fun onPageScrollStateChanged(state: Int) {
                super.onPageScrollStateChanged(state)
            }
        })
}

Case 2 : If you are the one who follows MVVM architecture, and facing issue of refreshing tabs ,when you switch/swipe tabs means, the following solution will works fine for you, implement this in you child fragments of both...

          
    override fun onResume() {
        super.onResume()
       //our fragment willbe in onResume state , after it created, so every time 
      //when i switch/swipe onResume method of respective fragment will be called, 
     //so i called respective method to load my viewmodel ,so that it refresh/update 
     //everytime
        viewModel.yourRespectiveMethod(param1,param2)
    }

Upvotes: 0

ch65
ch65

Reputation: 323

Please try this cod:

@Override
public void setMenuVisibility(boolean visible) {
    super.setMenuVisibility(visible);

    if (isVisible()) {
        //refresh your page
    }
}

Upvotes: 2

Zon
Zon

Reputation: 19880

Here is the most compact approach, touching a single method in your Fragment class only:

public class MyFragment extends Fragment {

  @Override
  public void setUserVisibleHint(boolean isVisibleToUser) {

    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser) {

      // Refresh tab data:

      if(getFragmentManager() != null) {

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

Upvotes: 2

Edwin Wachs
Edwin Wachs

Reputation: 408

I know the answer is old, but... I found a solution. I can not tell if it's the best one, but in my case, solved.

In Activity:

@Override
public void onTabSelected(ActionBar.Tab tab,
        FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in
    // the ViewPager.
    mViewPager.setCurrentItem(tab.getPosition());


        if (tab.getPosition() == 0) {

            LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
            Intent i = new Intent("TAG_REFRESH");
            lbm.sendBroadcast(i);

        }

}

And your Fragment:

public class MyFragment extends Fragment {

MyReceiver r;
public void refresh() {
    //yout code in refresh.
    Log.i("Refresh", "YES");
}

public void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(context).unregisterReceiver(r);
}

public void onResume() {
    super.onResume();
    r = new MyReceiver();
    LocalBroadcastManager.getInstance(context).registerReceiver(r,
            new IntentFilter("TAG_REFRESH"));
}

private class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        MyFragment.this.refresh();
    }
}

Upvotes: 27

Michele La Ferla
Michele La Ferla

Reputation: 6884

I would use something similar to the following:

public class MainActivity extends FragmentActivity implements ActionBar.TabListener {

    private ViewPager ViewPager;
    private TabsPagerAdapter SectionsPagerAdapter;
    private ActionBar actionBar;

    private String[] tabs = { "Event Details", "Line-up", "Donations", };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

     // Initialisation
        ViewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        SectionsPagerAdapter = new TabsPagerAdapter(getSupportFragmentManager());

        ViewPager.setAdapter(SectionsPagerAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 

     // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name).setTabListener(this));
        }

        ViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });
    }

    @Override
    public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {

    }

    @Override
    public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
        ViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {

    }

//Attaching the fragments to the tabPagerAdapter
public class TabsPagerAdapter extends FragmentPagerAdapter {

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

        @Override
        public Fragment getItem(int index) {

            switch (index) {
            case 0:
                return new EventFragment();
            case 1:
                // Points to the Lineup class
                return new LineupFragment();
            case 2:
                // Points to the 
                return new DonationFragment();
            case 3:

                return new ConcertFragment();
            }

            return null;
        }
@Override
        public int getCount() {
            // get item count - equal to number of tabs
            return 4;
        }
    }

//Add your fragments here

Hope this helps you :)

Upvotes: 4

Related Questions