Ошибка: этот фрагмент должен содержать конструктор по умолчанию (открытый конструктор без аргументов)

Мой класс расширяет DialogFragment следующим образом:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

    EditText editDate;
    private Calendar dateTime = Calendar.getInstance();
    private SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMMM yyyy");

    public DatePickerFragment(EditText editText) {
        editDate = editText;
    }

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Use the current date as the default date in the picker
    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH);

    // Create a new instance of DatePickerDialog and return it
    return new DatePickerDialog(getActivity(), this, year, month, day);

}

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        dateTime.set(year, monthOfYear, dayOfMonth);
        editDate.setText(dateFormatter
                .format(dateTime.getTime()));
    }

}

И вот как я использую его в Activity:

public void showDatePickerDialog(View v) {
        new DatePickerFragment((EditText) v).show(getSupportFragmentManager(), "datePicker");
    }

И вызывается вот так:

    <EditText
        android:id="@+id/editDate"
        android:onClick="showDatePickerDialog" />

Но я всегда получаю:

Error: This fragment should provide a default constructor (a public constructor with no arguments)

Ответ 1

Новая версия Android SDK заставляет вас получить пустой конструктор no-args. Теперь это хорошая практика. Это позволяет сохранить состояние экземпляра в комплекте, и Android воссоздает фрагмент, вызывающий конструктор по умолчанию.

В этом случае у вас есть следующие решения:

Сначала создайте конструктор по умолчанию:

public DatePickerFragment() {}

Создайте экземпляр и установите EditText с помощью метода setter:

DatePickerFragment fragment = new DatePickerFragment();
fragment.setEditText(v); // create this setter
fragment.show();

Поскольку EditText является простым, вы также можете установить в качестве аргументов:

DatePickerFragment fragment = new DatePickerFragment();
Bundle bundle = new Bundle();
bundle.putExtra("EditText", v); 
fragment.setArguments(bundle); // setArguments is a method that already exists in fragments.
fragment.show(getSupportFragmentManager(), "DatePicker");

[EDIT] Как было предложено, попробуйте проигнорировать эти ошибки, настроив build.gradle следующим образом:

lintOptions { 
  abortOnError false 
  checkReleaseBuilds false 
} 

Это не остановит сборку вашего приложения, используя конструктор не по умолчанию в фрагментах.

Ответ 2

Вам нужно удалить этот конструктор

public DatePickerFragment(EditText editText) {
    editDate = editText;
}

Вы не должны передавать ссылку View на Fragment. Если вы хотите обновить EditText в Activity или в другом месте, используйте прослушиватель.

Ответ 3

      public DatePickerFragment() {}

        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                dateTime.set(year, monthOfYear, dayOfMonth);
             //   editDate.setText(dateFormatter
             //         .format(dateTime.getTime()));
            Intent intent = new Intent();
            intent.setAction("CUSTOM_INTENT_FOR_SETTING_EDITTEXT");
            Bundle bundle = new Bundle();
            bundle.putString("my_data", dateTime.getTime.toString());
            intent.putExtras(bundle);
            sendBroadcast(intent);
            }




public class SubmitFragment extends Fragment {

    View view;
    EditText editDate;
    String strDate;
    Button btnSubmit;

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

        editDate = (EditText) view.findViewById(R.id.editDate);

        btnSend = (Button) view.findViewById(R.id.buttonSend);
        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                strDate = editDate.getText().toString();
                Log.v("strDate..... >>>", strDate);

            }
        });

        return view;
    }


        // Our handler for received Intents. This will be called whenever an Intent
        // with an action named "CUSTOM_INTENT_FOR_SETTING_EDITTEXT" is broadcasted.
        private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            // Get extra data included in the Intent
            String message = intent.getStringExtra("my_data");
            Log.d("receiver", "message: " + message);
        *****// Use this message to set Edittext here...*****
          }
        };


        @Override
        protected void onPause() {
          // Unregister since the activity is about to be closed.
          LocalBroadcastManager.getInstance(getactivity()).unregisterReceiver(mMessageReceiver);
          super.onDestroy();
        }


        @Override
        protected void onResume() {
          // register the receiver here..
       super.onResume(); LocalBroadcastManager.getInstance(getactivity()).registerReceiver(mMessageReceiver,
              new IntentFilter("CUSTOM_INTENT_FOR_SETTING_EDITTEXT"));
        }
}

Надеюсь, это поможет. Что именно я делаю здесь, это использование localBroadcast для  сделайте нужный... другой способ мог бы использовать интерфейс к заданному контексту но одна неправильная вещь об этом подходе заключается в том, что когда приложение находится в фоновом режиме для long, он вернет null, когда oncreateview будет вызван снова.

Ответ 4

Добавить @SuppressLint ( "ValidFragment" )

перед вашим классом,

открытый класс DatePickerFragment extends

Я надеюсь, что это поможет вам