In the Android book for developers 3rd edition, authors Paul Deitel, Harvey Deitel, Alexander Wald, have an example in which DialogFragment is an anonymous inner class. Android Studio displays the message "Fragments should not be static". There was a question - in the android API, there have been some changes, and it is no longer possible to use fragments as anonymous classes? Or were there mistakes in the book? The book covers API23, AS API27

private OnClickListener guessButtonListener = new OnClickListener() { @Override public void onClick(View v) { Button guessButton = ((Button) v); String guess = guessButton.getText().toString(); String answer = getCountryName(correctAnswer); ++totalGuesses; // Увеличение количества попыток пользователя if (guess.equals(answer)) { // Если ответ правилен ++correctAnswers; // Увеличить количество правильных ответов // Правильный ответ выводится зеленым цветом answerTextView.setText(answer + "!"); answerTextView.setTextColor( getResources().getColor(R.color.correct_answer, getContext().getTheme())); disableButtons(); // Блокировка всех кнопок ответов // Если пользователь правильно угадал FLAGS_IN_QUIZ флагов if (correctAnswers == FLAGS_IN_QUIZ) { // DialogFragment для вывода статистики и перезапуска DialogFragment quizResults = new DialogFragment() { // Создание окна AlertDialog @Override public Dialog onCreateDialog(Bundle bundle) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage( getString(R.string.results, totalGuesses, (1000 / (double) totalGuesses))); // Кнопка сброса "Reset Quiz" builder.setPositiveButton(R.string.reset_quiz, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { resetQuiz(); } } ); return builder.create(); // Вернуть AlertDialog } }; // Использование FragmentManager для вывода DialogFragment quizResults.setCancelable(false); quizResults.show(getFragmentManager(), "quiz results"); } else { // Ответ правильный, но викторина не закончена // Загрузка следующего флага после двухсекундной задержки handler.postDelayed( new Runnable() { @Override public void run() { animate(true); // Анимация исчезновения флага } }, 2000); // 2000 миллисекунд для двухсекундной задержки } } else { // Неправильный ответ flagImageView.startAnimation(shakeAnimation); // Встряхивание // Сообщение "Incorrect!" выводится красным шрифтом answerTextView.setText(R.string.incorrect_answer); answerTextView.setTextColor(getResources().getColor( R.color.incorrect_answer, getContext().getTheme())); guessButton.setEnabled(false); // Блокировка неправильного ответа } } }; 

    3 answers 3

    A non-static inner class will hold a reference to the parent class. In this case, with a fragment, there is a potential memory leak, especially if the parent class is an activation.

    Perhaps the authors simply missed it, because the case is quite specific for Android.

      Fragment cannot be an anonymous class. When restoring the activation, the FragmentManager can try to recreate the fragment through reflection.

      You will get an error

       android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.squareup.MyActivity$1: make sure class name exists, is public, and has an empty constructor that is public 

        This link was used to fix the error:
        https://habr.com/ru/post/259805/

        You must create a class that extends DialogFragment. It will display our dialog, and we will process the click of the OK button in the calling fragment MainActivityFragment in the onActivityResult method, which receives the code of the pressed button from the AlertDialogFragment called fragment:

         import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; public class AlertDialogFragment extends DialogFragment { public static int totalGuesses; @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { totalGuesses = getTargetRequestCode(); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setMessage(getString(R.string.results, totalGuesses, (1000 / (double) totalGuesses))); builder.setPositiveButton(R.string.reset_quiz, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { getTargetFragment().onActivityResult(totalGuesses, Activity.RESULT_OK, null); } }); return builder.create(); } } 

        In the calling fragment MainActivityFragment, we will create a showDialog method showing the dialog and process the click of the OK button in the onActivityResult method:

         //show dialog at the end of the game public void showDialog() { DialogFragment fragment = new AlertDialogFragment(); fragment.setTargetFragment(this, totalGuesses); fragment.setCancelable(false); fragment.show(getFragmentManager(), "quiz results"); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) resetQuiz(); } 

        Instead of the error code, we write the following code:

         if (correctAnswers == FLAG_IN_QUIZ) { showDialog(); }