Фрагменты вложенного диалога getActivity().findViewById возвращают нуль

#android #android-fragments #nullpointerexception #datepicker

#Android #android-фрагменты #исключение nullpointerexception #выбор даты

Вопрос:

Я использую этот класс для отображения средства выбора даты. Это работает следующим образом

  • Получение идентификатора текстового представления затем добавляет выбранную дату и время в это текстовое представление.

Когда я вызываю его из фрагментов, он работает нормально. Но когда я вызываю его из другого фрагмента диалога, он показывает средство выбора даты, а затем выдает исключение нулевого указателя при установке даты в текстовом поле. Пока фрагмент диалога все еще раздут в фоновом режиме и виден.

 public class DatePickerFragment extends DialogFragment {
    TextView dateTextView;
    Date tempDate;
    Boolean isCurrentDate;

    public static DatePickerFragment newInstance(int dateTextViewId, Boolean isCurrentDate) {
        DatePickerFragment fragment = new DatePickerFragment();
        Bundle bundle = new Bundle();
        bundle.putInt("textField", dateTextViewId);
        bundle.putBoolean("flag", isCurrentDate);
        fragment.setArguments(bundle);
        return fragment;
    }

    public void setDateTextView(TextView dateTextView) {
        this.dateTextView = dateTextView;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            this.dateTextView = (TextView) getActivity().findViewById(getArguments().getInt("textField"));
            isCurrentDate = getArguments().getBoolean("flag");
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Calendar c = Calendar.getInstance();
        int year = c.get(Calendar.YEAR);
        if (isCurrentDate == false) {
            year = c.get(Calendar.YEAR) - 18;
        }
        int month = c.get(Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);
        DatePickerDialog dialog = new DatePickerDialog(getActivity(), AlertDialog.THEME_HOLO_LIGHT, dateSetListener, year, month, day);
        if (isCurrentDate)
            dialog.getDatePicker().setMinDate(System.currentTimeMillis() - 1000);
        else
            dialog.getDatePicker().setMaxDate(c.getTimeInMillis());
        return dialog;
    }

    private DatePickerDialog.OnDateSetListener dateSetListener =
            new DatePickerDialog.OnDateSetListener() {
                public void onDateSet(DatePicker view, int year, int month, int day) {
                    DatePickerFragment.this.dateTextView.setText(view.getDayOfMonth()   "/"   (view.getMonth()   1)   "/"   view.getYear());
                }
            };

}
 

Вот как я раздуваю фрагмент диалога

 override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_transaction_filter_item_list, container, false)
        return binding.root
    }
 

И вот как я вызываю фрагмент средства выбора даты

 val calenderFragment =
                DatePickerFragment.newInstance(binding.fromDateTextView.id, false)
            calenderFragment.show(activity?.supportFragmentManager!!, "")
 

Сообщение об ошибке

     java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
 

Я не уверен, почему идентификатор не виден для действия.

Комментарии:

1. Как он работает нормально для фрагмента? вы вызываете getActivity().findViewById для этого представление, которое должно быть частью Activity not Fragment . Не рекомендуется передавать представление или идентификатор представления DialogFragment . Лучший способ сделать это — создать интерфейс и передать обратный вызов вызывающему компоненту с выбранной датой.

2. или вы можете создать общедоступный класс в своей деятельности и вызвать его из своего дочернего фрагмента

3. @ADM Я думаю, что он отлично работает с фрагментами, потому что у меня есть одно действие, и все фрагменты прикреплены к нему.

4. Почему у вас есть общедоступный сеттер setDateTextView ? При этом вы также вызываете findViewById ? Лучше использовать интерфейс, как я сказал выше в комментарии.