3

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?

mvalencaa
  • 451
  • 1
  • 6
  • 16

3 Answers3

7

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)

Parisa Baastani
  • 1,713
  • 14
  • 31
WarrenFaith
  • 57,492
  • 25
  • 134
  • 150
  • But you still need `onCreateView` method to inflate your layout. There are some instances where `setUserVisibleHint`is called before `onCreateView` and in this instance you will get nullPointerException. How would you handle this??? – Karue Benson Karue May 15 '16 at 20:12
0

Just call setOffscreenPageLimit() in onCreate() (after initializing ViewPager). The OffscreenPageLimit sets the number of pages that should be retained to either side of the current page (in your case 2). With this all of your fragments will be instantiate.

Source:Preload fragment's view in ViewPager on first run

Community
  • 1
  • 1
TheIT
  • 11,919
  • 4
  • 64
  • 56
0

Increase your setOffscreenPageLimit() to 2, so you know the fragments behind and in front of the currently selected fragment are still instantiated. After that, since you're using a ViewPager, you should look into setting an onPageChangeListener() on your ViewPager, and interface with your activity that way -- rather than using the lifecycle methods.

http://developer.android.com/reference/android/support/v4/view/ViewPager.OnPageChangeListener.html

Submersed
  • 8,810
  • 2
  • 30
  • 38