3

I have a FragmentActivity that contains four fragments displayed in a tab layout. The tabs are used to add or remove content in my database, and displayed in this order: Artist - Genre - Album - Song. The Album tab contains spinners for all artists and genres in the database, and those spinners should be updated as an artist or genre is added in their respective tab. This works for the Artist tab; however, when I add or remove something in the Genre tab, the change will not be displayed in Album unless I change the tab to Artist, or go to a separate Activity and then return.

The problem that I don't understand is that when I change the tab layout to be Artist - Genre - Song - Album, everything works perfectly fine. It seems that the tabs are only updating when they have viewed a separate activity or fragment, and then returned to the tab where the changes should have taken place. I also know that it is not a problem with the sql or methods that I use to refresh the spinners, because I have also tried to change the layout to Genre - Artist - Album - Song. In this case, Genre updates are successfully reflected in Album, but those in Artist are not, until I have moved two tabs away from Album.

It is difficult to explain much clearer than that, and I can post my code if needed, but it seems like the problem has something to do with navigating between the tabs directly next to one another.

I have also tried to inflate the add album layout in my genre fragment, and then update the spinner when I add or delete the genre.

This is the AddGenreFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View v = inflater.inflate(R.layout.add_genre_layout, container, false);
    addAlbum = inflater.inflate(R.layout.add_album_layout, container, false);
    spinGenre = (Spinner) addAlbum.findViewById(R.id.spinGenre);
    return v;
}

Then in the delete method:

// Refresh the spinners in Add Album
ArrayList<String> genreList = dbh.getAllGenres();       // Return all the genres in the database
if (!genreList.isEmpty()) {
    // Set the genre drop down box to be populated by all genres in the database
    adapterGenre = new ArrayAdapter<String>(addAlbum.getContext(),
    android.R.layout.simple_spinner_dropdown_item, genreList);
    adapterGenre.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinGenre.setAdapter(adapterGenre);
}

Edit:

I finally figured out the solution for this problem after stumbling on it in a different question. The reason that it was not updating and working right is because I am using a ViewPager with fragments for my tab adapter. The default with ViewPager is to load a maximum of 3 pages, or fragments, at a time. So if the user moves 3 tabs away from a certain tab, the orignal tab will be destroyed and onCreate will be called again when the original tab is re-selected.

To fix this problem, I simply added this line to my constructor for my TabsAdapter class:

mViewPager.setOffscreenPageLimit(NUMBER_OF_TABS - 1);

This finally fixed the issue I was having, as well as a few more that had been coming up.

1 Answers1

6

To solve this you have to understand how ViewPager works.

When you set adapter in ViewPager, ex 4 Fragments. Let's call | A | B | C | D |


From activity X you navigate to Activity Y which has ViewPager holding the above fragments.
X --> Y
      |--> | A | B | C | D |

When Y's view is rendered, i.e Fragment A is shown,

          Y
        | A | B |

Simultaneously fragment B is generated in pipeline.


When you move to fragment B, C is generated in pipeline, A is still alive.
          Y
    | A | B | C |

Any changes that you made in A that gets reflected in B is NOT rendered.


When you move to fragment C, D is generated in pipeline, B is still alive. A is killed
          Y
    | B | C | D |


When you move to D, C is retained, B is killed.
          Y
    | C | D |


When you move back now to C, B is generated freshly populating data as it was created for the first time.
          Y
    | B | C | D |

Now, the changes that has to reflected when data was changed in A in second step is available & can been seen in next step.


When you move back now to B, A is generated freshly populating data as it was created for the first time.
          Y
    | A | B | C |


ViewPager caches neighbouring views in both the sides, any changes that are made to effect view is neighbouring screen are not rendered, unless the view is recreated/refreshed forcefully either by moving to another activity or moving 2 views apart. You are experiencing the same & this is the default behaviour of ViewPager.

Compare A, B, C, D with your tabs, to resolve this have a look at Update ViewPager dynamically?

  • Make sure you use FragmentStatePagerAdapter instead of FragmentPagerAdapter as it does not kill fragments.
Community
  • 1
  • 1
VenomVendor
  • 15,064
  • 13
  • 65
  • 96