I am using a ViewPager2 with a FragmentStateAdapter to display several tabs of information. When a user updates their profile in the main Activity, I need to refresh the content inside the already-instantiated fragments. However, because ViewPager pre-loads fragments, my usual 'onResume' logic isn't firing when a user swipes back. Should I be using a ViewModel with LiveData, or is there a way to notify the adapter to recreate the fragments with new data?
3 answers
The most modern and recommended approach is to use a Shared ViewModel scoped to the Activity. By having your fragments observe a LiveData or StateFlow object within that ViewModel, any change made by the Activity will automatically trigger the observer inside your fragments, even if they are currently off-screen but still in the ViewPager's memory. This avoids the messy process of trying to get a direct reference to a fragment instance through the adapter. If you absolutely must refresh the entire fragment set, you can override getItemItemId and containsItem in your FragmentStateAdapter and then call notifyDataSetChanged(). However, the ViewModel approach is much more efficient as it only updates the specific UI components that need changing rather than destroying and recreating the entire fragment view hierarchy.
Using a Shared ViewModel is great for reactive updates, but if I have a very specific "refresh" button in my Fragment, should I still route that through the Activity's ViewModel or can the fragment handle its own local data fetch independently?
You can use adapter.notifyDataSetChanged() but make sure your adapter's createFragment logic is set up to pull the latest data. It's the "brute force" method but it works for simple apps.
Linda is right, but just a warning: notifyDataSetChanged in ViewPager2 can be tricky. You must ensure you've overridden the item ID methods, otherwise, the adapter might think the items haven't changed and won't refresh the view, leaving you with stale data.
If the refresh is local to that specific tab, the Fragment can definitely handle its own data fetch. However, keep in mind that if that data affects other tabs, you’ll still want to sync it through the shared ViewModel. A common pitfall is fetching data in onCreateView, which might only happen once. If you want the refresh to happen every time the user swipes to that tab, you should look into the onResume override or, in ViewPager2, use a lifecycle observer to detect when the fragment becomes the primary item.