Android ViewPager + Fragments with dynamic ListViews
Q

3

2

In my app I have activity with tabs (let's say 10 tabs). Each tab page contains Fragment with ListView(data displayed in this ListView is loaded dynamically from my server). I use ViewPagerto display these pages. I don't want to keep all the Fragments in memory, so I decided to use FragmentStatePagerAdapter (My adapter class extends these class).

  1. Let's say 3rd tab is selected. Then, when I go for example to the first tab, Fragment for this tab should be created from scratch (that's fine, it's how FragmentStatePagerAdapterworks) but without restoring previous state of this fragment (e.g., ListViewshouldn't be scrolled to the position saved when this Fragment was last accessed - now it is scrolled). So my first question is: how can I achieve such a behaviour? In other words, I want my adapter not to restore Fragmentstate, when it is created from scratch.

  2. Once again, let's say 3rd tab is selected. Then, when I go for example to the second tab, Fragmentfor this tab should be still in memory (that's fine, it's how FragmentStatePagerAdapterworks), but in this situation I want to decide if my ListViewdata should be updated (depending on some conditions). How can I notify this Fragment that it's selected?

Quincuncial answered 14/12, 2014 at 21:22 Comment(0)
C
0

For #1, take a look at this blog post. They talk about fixing FragmentStatePagerAdpater to handle the case where the fragment class for an index changes, which isn't exactly what you want. However, it shows in detail how state is saved/restored and you should be able to figure out how to prevent it from there.

For #2, implement OnPageChangeListener in the Fragment that holds the ViewPager. Then use this to get the current fragment when it changes so you can call some public method on it, telling it to update.

Cucumber answered 15/12, 2014 at 0:48 Comment(1)
This is exactly what I've done, before you posted your answer. I implemented my own PagerAdapter using FragmentStatePagerAdapter code without state saving/restoring parts. It is useful for my second problem too, because now, in my own adapter, I have an easy access to current Fragment (since there is internal Fragments list - no need to have additional map/array). I was only afraid if my idea was correct, but your answers is exactly the same, so I'm sure now. Thanks a lot.Quincuncial
S
0

I want my adapter not to restore Fragmentstate, when it is created from scratch.

add below code to the FragmentStatePagerAdapter

@Override
public int getItemPosition(Object object){
    return PagerAdapter.POSITION_NONE;
}

How can I notify this Fragment that it's selected?

When you load each fragment in getItem of fragmentStatePagerAdapter also pass position to the fragment using getInstance(the example of the link is good) design pattern. in the onPageSelected(int position) call a LocalBroadcastManager and put position as an extra. in each fragment check the intent and if that position in the extra is the same of the position stored in the fragment that means user selects that fragment so in onReceive method update the list.

Synesthesia answered 15/12, 2014 at 3:32 Comment(1)
1. I've tested your solution and it doesn't work and I've checked why. According to ViewPager source code, when after calling there mAdaper.getItemPosition(someObject) it returns POSITION_NONE, Fragment for this page is destroyed (adapter saves Fragment state before destroying it), but it still doesn't prevent FragmentStatePagerAdapter from restoring Fragments state when it is recreated. What's more it seems to be inefficient, because each time you call notifyDataSetChanged() all Fragmentswill be destroyed and recreated. 2. That's fine, but I've choosen simpler solution.Quincuncial
L
-1

for #1, AFAIK, when go to the first tab, associated with that tab's Fragment would create once more just like it never visit if you're used FragmentStatePagerAdapter. now you said the ListView is scrolled, are you sure you're using FragmentStatePagerAdapter??

in other hand, if you're using FragmentPagerAdapter, it would detaching all the off Fragments from the FragmentManager but keep them in memory so that's why when you come back from 3rd tab to 1st tab directly you saw the ListView stay at last state. the behavior your mentioned make me feel that it seems you're using FragmentPagerAdapter rather than FragmentStatePagerAdapter.

if you confirm that was FragmentStatePagerAdapter, I believe if you don't restore the state manually(i.e. working with the onSaveInstanceState() method in Fragment), the come back Fragment will certainly restore as just been born.

for #2, if you want to do something when Fragment comes fully visible, you can override the setUserVisibleHint method to putting your code over there.

public class YourFragement extend android.support.v4.app.Fragment {
    ...
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (conditions satisfied) {
            // do your job
        }
    }
    ...
}
Licketysplit answered 15/12, 2014 at 4:43 Comment(2)
Both FragmentPagerAdapter and FragmentStatePagerAdapter have the same visible semantics - the only difference is that the former retains the Fragment objects themselves, and the latter retains only their states. Both detaching and destroying a Fragment causes it's Views to be destroyed, and reattaching the Fragment has the same semantics as creating a new Fragment with the same saved state.Migdaliamigeon
@Migdaliamigeon yes, you're right, I paid much attention at the source code finally find out where the FragmentManager destroy Fragment's view, PagerAdater has not part on this mechanism. thanks for your remind, and apologize to everybody for my mistake.Licketysplit

© 2022 - 2024 — McMap. All rights reserved.