Reputation: 1117
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:
- detach attach fragment in onTabSelected (nothing happens)
- remove add fragment in onTabSelected (nothing happens)
- setOffscreenPageLimit(0) (Nothing happens)
- 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
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
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
Reputation: 323
Please try this cod:
@Override
public void setMenuVisibility(boolean visible) {
super.setMenuVisibility(visible);
if (isVisible()) {
//refresh your page
}
}
Upvotes: 2
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
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
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