Seekbar behaving unexpectedly when switching from one tab to another

Asked

Viewed 333 times

0

I have an app with ViewPager and three tabs (tabs), each displaying one Fragment that I seek to preserve in memory so that new ones are not instantiated Fragments every change of tab/screen.

public class TabsPagerAdapter extends FragmentPagerAdapter {

    private Fragmento0 mFragmento0 = null;
    private Fragmento1 mFragmento1 = null;
    private Fragmento2 mFragmento2 = null;


    public TabsPagerAdapter(FragmentManager fm, ViewPager viewPager) {
        super(fm);
    }

    @Override
    public Fragment getItem(int indice) {

        switch(indice){
        case 0:
            if (mFragmento0 == null) {
                mFragmento0 = new Fragmento0();
            }
            return mFragmento0;
        case 1:
            if (mFragmento1 == null) {
                mFragmento1 = new Fragmento1();
            }
            return mFragmento1;
        case 2:
            if (mFragmento2 == null) {
                mFragmento2 = new Fragmento2();
            }
            return mFragmento2;
        }
        return null;
    }

    ...

Fragmento0 has a SeekBar with the default value 60, defined in the layout of the same, and above it a TextView informing the current value of the SeekBar:

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceMedium"
    android:gravity="center_horizontal"/>
<SeekBar
    android:id="@+id/seekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="120"
    android:progress="60"/>

This is the relevant part of Fragmento0.onCreateView():

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragmento_0, container, false);

    mTextView = (TextView)rootView.findViewById(R.id.textView);
    mSeekBar = (SeekBar) rootView.findViewById(R.id.seekBar);
    mTextView.setText(mSeekBar.getProgress() + " minutos");

    ...
}

When I change the flap, I realize that the SeekBar behaves strangely: when I change its value to be different from the standard and change from tab 0 to tab 1, when returning to tab 0 the value is maintained, what is expected. But when I switch from tab 0 to tab 2, when I return to tab 0 the position of SeekBar does not change but the TextView indicates the default value again 60.

Debugging the code I discovered that Fragmento0.onCreateView() is not being called in the first case, which I believe is expected, but is being called in the second. Why? I don’t make any transactions with the Fragments, I move none to the back stack for example.

According to the life cycle of Fragments, is that right to happen? How do I correct this behavior? Would I have to use onSaveInstanceState()? (tried and didn’t work). But why in one case the view is recreated and in the other not? And why the call to onCreateView(), in making inflate in the layout, does not restore the default value of SeekBar?

1 answer

0


João Vitor, this behavior of ViewPager that is correct.

The ViewPager always destroys the View, but keeps the Fragment saved, see the default value 1 of OffscreenPageLimit. It holds only one Fragment that is out of sight, the last that was seen, so that when arriving at the third Fragment, he destroys the first.

In your case, there are two solutions:

  1. Setar the offscreenPageLimit of ViewPager for 3 or as many as you want, this prevents the destruction of the View. Which brings a benefit if the burden of view is slow, and the harm View will remain in memory.
  2. Implement the onSaveInstanceState saving the entire state of the screen, and onCreateView use the savedInstanceState to restore status again. Viewing documentation from Fragment, he says the state saved in onSaveInstanceState will be available on onCreateView.

Regarding your last question, the Fragments by default save its state when some configuration of the Activity changes (rotation for example), as described by the attribute retainInstance. I don’t know if in your case there was screen rotation when you noticed this problem, can you describe a case where it always occurs? I believe it is the case to realize another question maybe, I’m not sure.

  • Thank you for your reply. Setar the offscreenPageLimit worked. I am forcing the application not to rotate the screen, but I did not understand your recommendation on my last question, because my antepenultimate paragraph describes the situation where the problem always occurs. Also, onSaveInstanceState does not seem to work because the fragment does not get to be destroyed (called onDestroy), only your view.

  • Your last question, I believe, involves the issue of Retaininstace that takes place behind the "cloths" and that saves the state without the developer needing to do anything. But I’m not sure about that because I’ve never had to use it, and sometimes it’s gotten in my way. In your case, I don’t know if this is what causes the default value problem (not showing up) when rebuilding the view. It would be good to investigate by analyzing the Bundle of the saved state.

  • I complemented my previous comment including my experience with onSaveInstanceState.

  • This problem of onSaveInstanceState not being called might make sense like you said, but here’s how to save the state in this case... I can take a look and update my response.

  • I will accept the answer anyway because the problem has been solved, but if I have to supplement your answer in relation to this problem, I would appreciate it.

  • I will take a look and soon add my answer.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.