【问题标题】:Prevent ViewPager from always initialize the next fragment (position n+1)防止 ViewPager 总是初始化下一个片段(位置 n+1)
【发布时间】:2014-01-14 17:53:44
【问题描述】:

我正在使用ViewPager 进行注册向导,其中包含 5 个片段:FragmentA -> FragmentB -> FragmentC -> FragmentD -> FragmentE。 FragmentD 需要来自 FragmentC 的数据,以便在显示其视图时向用户显示一些信息。问题是在向用户显示 FragmentC 时初始化了 FragmentD,这意味着 FragmentD 所需的数据尚未准备好。因此,FragmentD 无法正确显示数据,因为它的生命周期初始化方法(我用来从 FragmentC 获取数据)已被调用。

我已经尝试设置pager.setOffscreenPageLimit(0),强制ViewPager 始终重建片段,但这不可能,因为 1 是接受的最小值。

这是我的 FragmentC 代码的简历:

@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;
        }
    }
}

这是我的 FragmentD 代码的简历:

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();
}

每个editText (text0, text1, text2, text3) 中的值取决于之前在 FragmentC 所做的选择。但就像我之前说的,onActivityCreatedonStart 在 FragmentC 初始化时被调用,所以用户还没有选择任何选项,即 choice 总是带有默认值,不要无论用户选择了哪个选项。

我真的不知道该怎么办...有人有什么想法吗?

【问题讨论】:

    标签: android android-fragments android-viewpager


    【解决方案1】:

    忘记setOffscreenPageLimit() 并覆盖setUserVisibleHint(boolean) 方法。

    检查该方法的参数是否为真,并使用那里的给定数据更新 UI。

    请注意,上述方法已被弃用,因此您应该改用FragmentTransaction.setMaxLifecycle(Fragment, Lifecycle.State)。 欲了解更多信息,请访问:

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

    【讨论】:

    • 这正是我所需要的,@WarrenFaith!太感谢了! =D
    • 但是你仍然需要onCreateView 方法来扩展你的布局。在某些情况下,setUserVisibleHintonCreateView 之前被调用,在这种情况下您将得到 nullPointerException。你会怎么处理这个???
    【解决方案2】:

    只需在 onCreate() 中调用 setOffscreenPageLimit()(在初始化 ViewPager 之后)。 OffscreenPageLimit 设置应保留到当前页面任一侧的页面数(在您的情况下为 2)。这样,您的所有片段都将被实例化。

    来源:Preload fragment's view in ViewPager on first run

    【讨论】:

      【解决方案3】:

      将您的setOffscreenPageLimit() 增加到2,这样您就知道当前所选片段后面和前面的片段仍然被实例化。之后,由于您使用的是ViewPager,因此您应该考虑设置onPageChangeListener() 在您的ViewPager 上,并以这种方式与您的活动交互——而不是使用生命周期方法。

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

      【讨论】:

        猜你喜欢
        • 2016-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多