I'm trying to unlock the application, it gives an error, and everything works fine. As it seems to me DatePickerFragment swears. What is it? How to fix?

Is there a problem here?

//Календарь возвращает текущее время final Calendar calendar = Calendar.getInstance(); //Добавим к времени час если указана только дата (без времени), для срабатывания. calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1 ); //Слушатель для выбора Даты etDate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //Проверка на длину текста в поле if (etDate.length() == 0) { etDate.setText(" "); } DialogFragment datePickerFragment = new DatePickerFragment() { @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, monthOfYear); calendar.set(Calendar.DAY_OF_MONTH, dayOfMonth); etDate.setText(Utils.getDate(calendar.getTimeInMillis())); } //При нажатии "Отмена" текст не устанавливался @Override public void onCancel(DialogInterface dialog) { etDate.setText(null); } }; datePickerFragment.show(getFragmentManager(), "DatePickerFragment"); } }); //Слушатель для выбора Времени etTime.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (etTime.length() == 0){ etTime.setText(" "); } DialogFragment timePickerFragment = new TimePickerFragment() { @Override public void onTimeSet(TimePicker view, int hourOfDay, int minute) { calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); calendar.set(Calendar.MINUTE, minute); calendar.set(Calendar.SECOND, 0); etTime.setText(Utils.getTime(calendar.getTimeInMillis())); } @Override public void onCancel(DialogInterface dialog) { etTime.setText(null); } }; timePickerFragment.show(getFragmentManager(), "TimePickerFragment "); } }); builder.setPositiveButton(R.string.dialog_add, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { task.setTitle(etTitle.getText().toString()); task.setStatus(ModelTask.STATUS_CURRENT); if (etDate.length() != 0 || etTime.length() != 0 ){ task.setDate(calendar.getTimeInMillis()); AlarmHelper alarmHelper = AlarmHelper.getInstance(); alarmHelper.setAlarm(task); } task.setStatus(ModelTask.STATUS_CURRENT); addingTaskListener.onTaskAdded(task); dialog.dismiss(); } }); builder.setNegativeButton(R.string.dialog_cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { addingTaskListener.onTaskAddingCancel(); dialog.cancel(); } }); 

Class DatePickerFragment

 public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Calendar c = Calendar.getInstance(); int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_MONTH); return new DatePickerDialog(getActivity(), this, year, month, day); } @Override public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { } 

The fragment is taken out separately ...

I did as they said the check showed this piece of code, below I will indicate the line

  @Override public void addTask(ModelTask newTask, boolean saveToDB) { int position = -1; ModelSeparator separator = null; for (int i = 0; i < adapter.getItemCount(); i++) { if (adapter.getItem(i).isTask()) { ModelTask task = (ModelTask) adapter.getItem(i); if (newTask.getDate() < task.getDate()) { position = i; break; } } } if (newTask.getDate() != 0) { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(newTask.getDate()); if (calendar.get(Calendar.YEAR) < Calendar.getInstance().get(Calendar.YEAR)) { newTask.setDateStatus(ModelSeparator.TYPE_OVERDUE); if (!adapter.containsSeparatorOverdue) { adapter.containsSeparatorOverdue = true; separator = new ModelSeparator(ModelSeparator.TYPE_OVERDUE); } } else if (calendar.get(Calendar.YEAR) > Calendar.getInstance().get(Calendar.YEAR)) { newTask.setDateStatus(ModelSeparator.TYPE_FUTURE); if (!adapter.containsSeparatorFuture) { adapter.containsSeparatorFuture = true; separator = new ModelSeparator(ModelSeparator.TYPE_FUTURE); } } else if (calendar.get(Calendar.DAY_OF_YEAR) < Calendar.getInstance().get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.YEAR) == Calendar.getInstance().get(Calendar.YEAR)) { newTask.setDateStatus(ModelSeparator.TYPE_OVERDUE); if (!adapter.containsSeparatorOverdue) { adapter.containsSeparatorOverdue = true; separator = new ModelSeparator(ModelSeparator.TYPE_OVERDUE); } } else if (calendar.get(Calendar.DAY_OF_YEAR) == Calendar.getInstance().get(Calendar.DAY_OF_YEAR) && calendar.get(Calendar.YEAR) == Calendar.getInstance().get(Calendar.YEAR)) { newTask.setDateStatus(ModelSeparator.TYPE_TODAY); if (!adapter.containsSeparatorToday) { adapter.containsSeparatorToday = true; separator = new ModelSeparator(ModelSeparator.TYPE_TODAY); } } else if (calendar.get(Calendar.DAY_OF_YEAR) == Calendar.getInstance().get(Calendar.DAY_OF_YEAR) + 1 && // <-- Ругается на эту строку на кусок после "==" - Сообщение такое - "Must be one of: Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY less... (Ctrl+F1)" calendar.get(Calendar.YEAR) == Calendar.getInstance().get(Calendar.YEAR)) { newTask.setDateStatus(ModelSeparator.TYPE_TOMORROW); if (!adapter.containsSeparatorTomorrow) { adapter.containsSeparatorTomorrow = true; separator = new ModelSeparator(ModelSeparator.TYPE_TOMORROW); } } else if (calendar.get(Calendar.DAY_OF_YEAR) > Calendar.getInstance().get(Calendar.DAY_OF_YEAR) + 1 && calendar.get(Calendar.YEAR) == Calendar.getInstance().get(Calendar.YEAR)) { newTask.setDateStatus(ModelSeparator.TYPE_FUTURE); if (!adapter.containsSeparatorFuture) { adapter.containsSeparatorFuture = true; separator = new ModelSeparator(ModelSeparator.TYPE_FUTURE); } } } 
  • Where and under what actions does an error appear and is displayed? - Yuriy SPb
  • When trying to generate a project from "Debag" to "release" (Android Studio) - Eugene Zaychenko
  • I think that this mistake hints at the fact that somewhere you have a fragment declared not in a separate file and not in the form of an internal static class, but in the form of an anonymous class. In theory, if you put this fragment into a separate file, then the problem will disappear - YuriiSPb
  • You have added a large piece of code, but I don’t see something on which the analyzer swears - lllyct
  • I suffer with the same problem for several days already. @Eugene Zaychenko, did you solve the problem? - Alexey Sukhilin

2 answers 2

You have somewhere declared a fragment as an anonymous or non-static nested class. It is not good to do this, because the system can beat the activity along with the fragment, for example, when it is folded, and then restore it. During restoration, a new fragment instance can be created and for this purpose a default constructor without parameters will be used. For nested non-static classes, all constructors implicitly accept an instance of a class as a parameter (roughly speaking, to clarify the situation, it will do), therefore all fragments should be declared as separate classes, or as static nested classes. Those. instead

 class MyFragment extends Fragment { 

declared inside another class must be

 static class MyFragment extends Fragment { 

And yes, you can’t simply refer to an instance of an external class, you’ll have to get it somehow.

Well and still such code should be avoided:

 new MyFragment() { // some methods overriding } 

This is an anonymous class. And it implicitly refers to the class in which you declared it.

Plus, each fragment must have a constructor without parameters.

  • I added code in which there can be a problem, but everything seems to be correct here. The fragment is moved to a separate file, and when clicked, we create its new instance. Is there a mistake? - Eugene Zaychenko
  • @EvgeniyZaychenko c DatePickerFragment seems to be all right, but the error may occur due to another fragment. Try in the Analyze-> Inspect Code studio, in the InspectionProfile settings, tick only Fragment not instantiatable and run the check. In theory, you should see not only an abstract error message, but also a specific string or at least a class. - lllyct
  • And do not forget to pre-clone the Inspections profile and somehow return everything back. It is still useful to you and will highlight all sorts of different errors. - lllyct
  • I did as I wrote, I gave out 1 line, I remember she cursed it earlier, but I clicked something (I chose one of the suggested solutions) and the underscore disappeared, but everything is not so simple :)) In the code I indicated a line that was being cursed. - Eugene Zaychenko
  • In the last block of code, move the horizontal scroll runner to the center - Eugene Zaychenko

Add to build.gradle

 android { lintOptions { abortOnError false } }