4

I have a swipe tab with three different fragments for three tabs. getItem method in FragmentPagerAdapter called twice. My first tab loads local data and have different layout than next two tabs (tab2, tab3). Tab2 and Tab3 fetches data from server and load accordingly.

My problem is, for first time loading getItem called twice and this causes tab1 and tab2 both executed. Though tab1 only consist local data but because of twice calling tab2 executed and fetch data from server.

I don't want to execute tab2 and it's functionality while I'm in tab1 and so forth.

The getItem() code:

@Override public Fragment getItem(int position) { 
    Fragment fragment = null; 
    switch (position) { 
        case 0: fragment = new CommentFragment(); break; 
        case 1: fragment = new AllPostFragment(); break; 
        case 2: fragment = new TodayFragment(); break; 
    } 
    return fragment; 
}

So, I'm looking for a solution. Please help me out if you can.

debug.error
  • 55
  • 1
  • 9
  • Can you share the code – playmaker420 May 20 '15 at 07:07
  • @Override public Fragment getItem(int position) { Fragment fragment = null; switch (mViewPager.getCurrentItem()) { case 0: fragment = new CommentFragment(); break; case 1: fragment = new AllPostFragment(); break; case 2: fragment = new TodayFragment(); break; } return fragment; } here is my getItem method. CommentFragment have no server interaction. But allPostFragement fetch data from server. So for the first time, case matched for both position 0 and 1 And execute AllPostFragment and start fetching data from server. – debug.error May 20 '15 at 09:01
  • added code from OPs comment – Manuel Allenspach May 22 '15 at 11:28

3 Answers3

12

In ViewPager there is a limit how many screens (Fragments) your ViewPager will load. You can set this by calling ViewPagers setOffscreenPageLimit method.

HOWEVER if you inspect the ViewPagers code, it tells you that you must atleast load 1 offscreen page:

private static final int DEFAULT_OFFSCREEN_PAGES = 1;

public void setOffscreenPageLimit(int limit) {
    if (limit < DEFAULT_OFFSCREEN_PAGES) {
        Log.w(TAG, "Requested offscreen page limit " + limit 
            + " too small; defaulting to " + DEFAULT_OFFSCREEN_PAGES);
        limit = DEFAULT_OFFSCREEN_PAGES;
    }
    // ...
}

Bottom line: I don't think you can load the current Fragment only, sorry.

EDIT: But you can do something like this in your Fragments if you want to load, lets say, data from network only when Fragments comes visible to user:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // Fetch data or something...
    }
}
vilpe89
  • 4,656
  • 1
  • 29
  • 36
  • Your suggestion sounds good. This approach might work. I'll try and let you know. Thanks man! – debug.error May 20 '15 at 09:03
  • This is exactly what I wanted. Wonderful solution. I didn't know about this method. I spent almost 3-4 days. Tried many different ways to fix this up. setUserVisibleHint method simply solved my problem. So brilliant! Thanks a billion. – debug.error May 20 '15 at 09:34
0

When you have two fragments in a tab, normally both fragments will start and will be running "in parallel". This is a normal behaviour. You can use some sort of EventBus or similar to manually control the lifecycle of the fragments.

webo80
  • 3,365
  • 5
  • 35
  • 52
  • Thanks for your reply. Yes, both fragments run concurrently. Actually here is my problem. I don't want to fetch data from server in Tab2 while first time loading. I've seen that getItem called twice and I've used SWITCH_CASE between fragment based on position. And for first time CASE matched for position 0 and position 1. Though Tab1 visible but there is method which fetch data from server getting called in Tab2. I will check out what you referred. Thanks. – debug.error May 20 '15 at 08:43
  • You can trigger an event, eg: Instead of call server in onCreate / whatever, call on a callback that is waiting for the second tab being selected. – webo80 May 20 '15 at 08:46
  • ' @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser) { // Fetch data or something... } }' this method solved my problem. vilpe89 answer worked perfectly. – debug.error May 20 '15 at 09:36
0

Yes. call this method in each fragment and call your methods and etc on it:

  override fun setUserVisibleHint(isVisibleToUser: Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        if(isVisibleToUser)
            loadData() 
    }
  • Don't write it in the first fragment!
Hossein Yousefpour
  • 3,827
  • 3
  • 23
  • 35