片段未附加到上下文 - 第二次导航到片段后发生错误

Fragment not attached to a context - error occurs after navigating to a fragment for the second time

我正在做一个使用单一 activity 架构的应用程序。导航由导航组件完成。我的导航图的相关片段如下所示:

在从 listLensesFragment 到 generalLensInformationFragment 的转换中添加了一个包。

generalLensInformationFragment、leftLensDetailsFragment 和 rightLensDetailsFragment 这三个片段正在使用共享的 ViewModel。

到目前为止,所有的事情都有效——但是当我第二次从 listLensesFragment 导航到 generalLensInformationFragment 时,应用程序在使用 getArguments():

接收包时崩溃了
 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment_general_lens_information, container, false);

        manageLensViewModel = new ViewModelProvider(getActivity()).get(ManageLensViewModel.class);

        Bundle bundle = this.getArguments();

在调试模式下,检查“this”,里面有它的对象。

但是 logcat 输出看起来如下:

java.lang.IllegalStateException: Fragment LeftLensDetailsFragment{f731448} (30ef95ba-f165-4385-8b84-c63a7eb435c5) not attached to a context.
        at androidx.fragment.app.Fragment.requireContext(Fragment.java:900)
        at androidx.fragment.app.Fragment.getResources(Fragment.java:964)
        at androidx.fragment.app.Fragment.getString(Fragment.java:986)

我不知道如何处理这些错误。 在我的代码最相关的部分下方。

单击 listLensesFragment 中的编辑对象:

    adapter.setOnItemEditClickListener(new LensAdapter.OnItemEditClickListener() {
        @Override
        public void onItemClick(LensWithWears lensWithWears) {

            Bundle bundle = new Bundle();
            Lens lens = lensWithWears.lens;
            bundle.putParcelable(BUNDLE_LENS, lens);
            navController.navigate(R.id.action_listLensesFragment_to_generalLensInformationFragment, bundle);
            }
        });

关于创建我的 GeneralLensInformationFragment 的视图:

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view =  inflater.inflate(R.layout.fragment_general_lens_information, container, false);

    manageLensViewModel = new ViewModelProvider(getActivity()).get(ManageLensViewModel.class);

    Bundle bundle = this.getArguments();

    Lens lens;
    if (bundle.getParcelable(BUNDLE_LENS) != null) {
        manageLensViewModel.action = ACTION_UPDATE;
        lens = bundle.getParcelable(BUNDLE_LENS);
        manageLensViewModel.setLens(lens);
    }
    return view;
}

leftLensDetailsFragment

public class LeftLensDetailsFragment extends Fragment {
    public static final String BUNDLE_LENS = "com.studioz.lenstimer.BUNDLE_LENS";
    public static final String STRING_ACTION = "com.studioz.lenstimer.STRING_ACTION";

    public static final int ACTION_CREATE = 1;
    public static final int ACTION_UPDATE = 2;

    SliderConverter sl;

    private TextView txtLensName, txtShowDiopters, txtShowDiameter, txtShowBaseCurve;
    private TextInputLayout edtTextBrandLayout, edtTextModelLayout;
    private TextInputEditText edtTextBrand, edtTextModel;
    private Slider sliderSelectDiopters, sliderSelectDiameter, sliderSelectBaseCurve;
    private CheckBox cbUniformLenses;
    private MaterialButton btnNextLens, btnCreateLens;
    private ManageLensViewModel manageLensViewModel;

    public LeftLensDetailsFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_left_lens_details, container, false);

        manageLensViewModel = new ViewModelProvider(getActivity()).get(ManageLensViewModel.class);
        sl = new SliderConverter();

        return view;
    }


    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        initializeViews(view);
        setFieldValues();

        edtTextBrand.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                Lens lens = manageLensViewModel.getLens().getValue();
                lens.setBrandLeft(edtTextBrand.getText().toString());
                manageLensViewModel.setLens(lens);
            }
        });

        edtTextModel.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                Lens lens = manageLensViewModel.getLens().getValue();
                lens.setModelLeft(edtTextModel.getText().toString());
                manageLensViewModel.setLens(lens);
            }
        });

        sliderSelectDiopters.addOnChangeListener(new Slider.OnChangeListener() {
            @Override
            public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
                double diopters = sl.convertToDoubleFromDioptersSlider(sliderSelectDiopters.getValue());
                txtShowDiopters.setText(String.valueOf(diopters) + " " + getString(R.string.unitDiopters));
            }
        });

        sliderSelectDiameter.addOnChangeListener(new Slider.OnChangeListener() {
            @Override
            public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
                double diameter = sl.convertToDoubleFromDiameterSlider(sliderSelectDiameter.getValue());
                txtShowDiameter.setText(String.valueOf(diameter) + " " + getString(R.string.unitDiameter));
            }
        });

        sliderSelectBaseCurve.addOnChangeListener(new Slider.OnChangeListener() {
            @Override
            public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) {
                double basecurve = sl.convertToDoubleFromBaseCurveSlider(sliderSelectBaseCurve.getValue());
                txtShowBaseCurve.setText(String.valueOf(basecurve) + " " + getString(R.string.unitBaseCurve));
            }
        });

        cbUniformLenses.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    btnCreateLens.setVisibility(View.VISIBLE);
                    btnNextLens.setVisibility(View.GONE);
                } else {
                    btnCreateLens.setVisibility(View.GONE);
                    btnNextLens.setVisibility(View.VISIBLE);
                }
            }
        });

        NavController navController = Navigation.findNavController(view);

        btnNextLens.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                double d = 0;
                Lens lens = manageLensViewModel.getLens().getValue();

                d = sl.convertToDoubleFromDioptersSlider(sliderSelectDiopters.getValue());
                lens.setDioptersLeft(d);

                d = sl.convertToDoubleFromDiameterSlider(sliderSelectDiameter.getValue());
                lens.setDiameterLeft(d);

                d = sl.convertToDoubleFromBaseCurveSlider(sliderSelectBaseCurve.getValue());
                lens.setBasecurveLeft(d);

                lens.setUniform(false);

                manageLensViewModel.setLens(lens);

                navController.navigate(R.id.action_leftLensDetailsFragment_to_rightLensDetailsFragment);
            }
        });

        btnCreateLens.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                double d = 0;
                Lens lens = manageLensViewModel.getLens().getValue();

                d = sl.convertToDoubleFromDioptersSlider(sliderSelectDiopters.getValue());
                lens.setDioptersLeft(d);

                d = sl.convertToDoubleFromDiameterSlider(sliderSelectDiameter.getValue());
                lens.setDiameterLeft(d);

                d = sl.convertToDoubleFromBaseCurveSlider(sliderSelectBaseCurve.getValue());
                lens.setBasecurveLeft(d);

                lens.setBrandRight(lens.getBrandLeft());
                lens.setModelRight(lens.getModelLeft());
                lens.setDioptersRight(lens.getDioptersLeft());
                lens.setDiameterRight(lens.getDiameterLeft());
                lens.setBasecurveRight(lens.getBasecurveLeft());

                lens.setUniform(true);

                manageLensViewModel.setLens(lens);

                if (manageLensViewModel.action == ACTION_CREATE) {
                    manageLensViewModel.insert(manageLensViewModel.getLens().getValue());
                }
                if (manageLensViewModel.action == ACTION_UPDATE) {
                    manageLensViewModel.update(manageLensViewModel.getLens().getValue());
                }

                navController.navigate(R.id.action_leftLensDetailsFragment_to_listLensesFragment);
            }
        });
    }

    private void setFieldValues() {
        Lens lens = manageLensViewModel.getLens().getValue();

        txtLensName.setText(lens.getName());
        edtTextBrandLayout.getEditText().setText(lens.getBrandLeft());
        edtTextModelLayout.getEditText().setText(lens.getModelLeft());

        if (lens.getDioptersLeft() != 0) {
            txtShowDiopters.setText(String.valueOf(lens.getDioptersLeft()) + " " + getString(R.string.unitDiopters));
            sliderSelectDiopters.setValue(sl.convertToFloatFromLensDiopters(lens.getDioptersLeft()));
        }

        if (lens.getDiameterLeft() != 0) {
            txtShowDiameter.setText(String.valueOf(lens.getDiameterLeft()) + " " + getString(R.string.unitDiameter));
            sliderSelectDiameter.setValue(sl.convertToFloatFromLensDiameter(lens.getDiameterLeft()));
        }

        if (lens.getBasecurveLeft() != 0) {
            txtShowBaseCurve.setText(String.valueOf(lens.getBasecurveLeft()) + " " + getString(R.string.unitDiopters));
            sliderSelectBaseCurve.setValue(sl.convertToFloatFromLensBaseCurve(lens.getBasecurveLeft()));
        }

        cbUniformLenses.setChecked(lens.isUniform());
    }

    private void initializeViews(View view) {
        txtLensName = view.findViewById(R.id.txtLensName);
        txtShowDiopters = view.findViewById(R.id.txtShowDiopters);
        txtShowDiameter = view.findViewById(R.id.txtShowDiameter);
        txtShowBaseCurve = view.findViewById(R.id.txtShowBaseCurve);
        edtTextBrandLayout = view.findViewById(R.id.edtTextBrandLayout);
        edtTextBrand = view.findViewById(R.id.edtTextBrand);
        edtTextModelLayout = view.findViewById(R.id.edtTextModelLayout);
        edtTextModel = view.findViewById(R.id.edtTextModel);

        sliderSelectDiopters = view.findViewById(R.id.sliderSelectDiopters);
        sliderSelectDiopters.setValue(sl.getSliderDioptersDefault());
        sliderSelectDiopters.setValueTo(sl.getSliderDioptersEnd());
        txtShowDiopters.setText(String.valueOf(sl.DEFAULT_DIOPTERS) + " " + getString(R.string.unitDiopters));

        sliderSelectDiameter = view.findViewById(R.id.sliderSelectDiameter);
        sliderSelectDiameter.setValue(sl.getSliderDiameterDefault());
        sliderSelectDiameter.setValueTo(sl.getSliderDiameterEnd());
        txtShowDiameter.setText(String.valueOf(sl.DEFAULT_DIAMETER) + " " + getString(R.string.unitDiameter));

        sliderSelectBaseCurve = view.findViewById(R.id.sliderSelectBaseCurve);
        sliderSelectBaseCurve.setValue(sl.getSliderBaseCurveDefault());
        sliderSelectBaseCurve.setValueTo(sl.getSliderBaseCurveEnd());
        txtShowBaseCurve.setText(String.valueOf(sl.DEFAULT_BASECURVE) + " " + getString(R.string.unitBaseCurve));

        btnNextLens = view.findViewById(R.id.btnNextLens);
        btnCreateLens = view.findViewById(R.id.btnCreateLens);

        cbUniformLenses = view.findViewById(R.id.cbUniformLenses);
        cbUniformLenses.setChecked(false);
        btnCreateLens.setVisibility(View.GONE);
        btnNextLens.setVisibility(View.VISIBLE);
    }
}

在上面的代码中,我停止在我的 ViewModel 中为我的 MutableLiveData 使用观察者。这似乎解决了问题,但不是推荐的方式。

这样当应用程序崩溃时观察到的数据:

    nameObserver = new Observer<Lens>() {
        @Override
        public void onChanged(Lens lens) {
            // do all the stuff from setFieldValues()...
        }
    };

    manageLensViewModel.getNameData().observe(this, nameObserver);

有人可以帮助我解决这个错误吗?我真的不知道现在该怎么办。 如果需要更多代码片段,请告诉我!

科特林

lifecycleScope.launchWhenResumed {
// do your work here 
}

Bö macht Blau 的回答帮助了我 - 使用 Fragment.viewLiefecycleOwner 完成了工作。

viewModel.getAllData().observe(getViewLifecycleOwner(), new Observer<List<LensWithWears>>() {
    ...do the job here...
});