Search code examples
androidandroid-fragmentsandroid-viewpager

Prevent ViewPager from always initialize the next fragment (position n+1)


I'm doing a wizard for registration using a ViewPager that have 5 fragments inside it: FragmentA -> FragmentB -> FragmentC -> FragmentD -> FragmentE. The FragmentD needs the data that comes from FragmentC to show some information to the user when its views are shown. The problem is FragmentD is initialized when FragmentC is being shown to the user, which means that the data necessary for the FragmentD isn't ready. Because of it, FragmentD cannot show the data properly because its lifecycle initializing methods (which I use to get data from FragmentC) have already been called.

I've already tried set pager.setOffscreenPageLimit(0), to force ViewPager always rebuild the fragments, but its not possible because 1 is the minimum value accepted.

Here is a resume of my FragmentC code:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    radio0 = (RadioButton) getView().findViewById(R.id.radio_0);
    radio0.setOnCheckedChangeListener(this);
    text0 = (TextView) getView().findViewById(R.id.description_0);
    setOnClickListener(text0, radio0);

    radio1 = (RadioButton) getView().findViewById(R.id.radio_1);
    radio1.setOnCheckedChangeListener(this);
    text1 = (TextView) getView().findViewById(R.id.description_1);
    setOnClickListener(text1, radio1);

    radio2 = (RadioButton) getView().findViewById(R.id.radio_2);
    radio2.setOnCheckedChangeListener(this);
    text2 = (TextView) getView().findViewById(R.id.description_2);
    setOnClickListener(text2, radio2);
}

@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    if (isChecked) {
        switch (buttonView.getId()) {
                    case R.id.radio_0:
            radio1.setChecked(false);
            radio2.setChecked(false);

            choice = 0;
            break;
        case R.id.radio_1:
            radio0.setChecked(false);
            radio2.setChecked(false);

            choice = 1;
            break;
        case R.id.radio_2:
            radio0.setChecked(false);
            radio1.setChecked(false);

            choice = 2;
            break;
        }
    }
}

And here is a resume of my FragmentD code:

private OnOptionSelectedListener callback;
private EditText edit0, edit1, edit2, edit3;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
        callback = (OnOptionSelectedListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement OnOptionSelectedListener");
    }
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    edit0 = ((EditText) getView().findViewById(R.id.edit_0));
    edit1 = ((EditText) getView().findViewById(R.id.edit_1));
    edit2 = ((EditText) getView().findViewById(R.id.edit_2));
    edit3 = ((EditText) getView().findViewById(R.id.edit_3));
}

@Override
public void onStart() {
    super.onStart();

    choice = callback.getChoice();

    edit0.setText(text0);
    edit1.setText(text1);
    edit2.setText(text2);
    edit3.setText(text3);
}

public interface OnOptionSelectedListener {
    public int getOption();
}

The values inside each editText (text0, text1, text2, text3) depends of the choice made before at FragmentC. But like I said before, onActivityCreated and onStart are being called when FragmentC is being initialized, so the user didn't selected none of the options yet, i.e., choice always come with the default value, don't matter which option the user have selected.

I really don't know what to do... Does anybody have some ideia?


Solution

  • Forget the setOffscreenPageLimit() and override the setUserVisibleHint(boolean) method.

    Check the parameter of that method for becoming true and update the UI with the given data there.

    Pay attention that above method is deprecated, so you should use FragmentTransaction.setMaxLifecycle(Fragment, Lifecycle.State) instead. For more information go:

    https://developer.android.com/reference/androidx/fragment/app/FragmentTransaction#setMaxLifecycle(androidx.fragment.app.Fragment,%20androidx.lifecycle.Lifecycle.State)