21

I'm trying to create an AlertDialog, by using the Builder and setting a custom view. When I try to inflate the view inside of onCreateDialog, I get a StackOverflowError..

Here is the code up to the point where it loops back to onCreateDialog:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState){
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setTitle(R.string.enter_time);

    LinearLayout outerLayout = (LinearLayout) getLayoutInflater(savedInstanceState)
            .inflate(R.layout.time_entry_dialog, null);
    ...
}

And here is the LogCat output:

02-28 22:30:04.220: E/AndroidRuntime(4250): FATAL EXCEPTION: main
02-28 22:30:04.220: E/AndroidRuntime(4250): java.lang.StackOverflowError
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.app.Activity.getSystemService(Activity.java:4009)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.view.LayoutInflater.from(LayoutInflater.java:210)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.view.ContextThemeWrapper.getSystemService(ContextThemeWrapper.java:75)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at com.android.internal.app.AlertController$AlertParams.<init>(AlertController.java:812)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.app.AlertDialog$Builder.<init>(AlertDialog.java:374)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.app.AlertDialog$Builder.<init>(AlertDialog.java:359)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at com.sweatyreptile.chee.runtimetracker.TimeEntryDialogFragment.onCreateDialog(TimeEntryDialogFragment.java:18)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.support.v4.app.DialogFragment.getLayoutInflater(DialogFragment.java:295)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at com.sweatyreptile.chee.runtimetracker.TimeEntryDialogFragment.onCreateDialog(TimeEntryDialogFragment.java:21)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.support.v4.app.DialogFragment.getLayoutInflater(DialogFragment.java:295)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at com.sweatyreptile.chee.runtimetracker.TimeEntryDialogFragment.onCreateDialog(TimeEntryDialogFragment.java:21)
02-28 22:30:04.220: E/AndroidRuntime(4250):     at android.support.v4.app.DialogFragment.getLayoutInflater(DialogFragment.java:295)
...etc

EDIT: I found this line in the source of DialogFragment.getLayoutInflater():

mDialog = onCreateDialog(savedInstanceState);

So.. if I can't get a LayoutInflator inside of onCreateDialog without causing infinite recursion, how do I inflate a view for a custom AlertDialog?

Nora Powers
  • 1,597
  • 13
  • 31

3 Answers3

34

If found the problem. DialogFragment.getLayoutInflater() contains a call to onCreateDialog(), so calling onCreateDialog() from within getLayoutInflater() creates an infinite loop.

I found the solution in this answer: https://stackoverflow.com/a/10585164/2020340

I'm not exactly sure if this is good form, because it doesn't really seem like it, but I replaced

getLayoutInflater(savedInstanceState)

with

getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Edit: They are the same. See this answer for details: https://stackoverflow.com/a/20995083/2020340

Nora Powers
  • 1,597
  • 13
  • 31
  • 1
    Is that an Android bug? I had this problem too, and to me calling onCreateDialog from within getLayoutInflater doesn't make sense? – medonja Dec 29 '15 at 10:37
  • 13
    `LayoutInflater.from(getContext())` seems to work as well. – swanson Mar 01 '18 at 21:23
  • 4
    `getActivity().getLayoutInflater()` also works, although you should also check for `getActivity()` returning `null` if you're using a v4 support library Fragment. See https://developer.android.com/reference/android/support/v4/app/Fragment.html#getActivity() – snark Mar 11 '18 at 17:48
  • 1
    Disappointing that 5 years later, the Android docs still guide people to use the _**wrong**_ method: `layoutInflater.inflate(...)` https://developer.android.com/guide/topics/ui/dialogs#kotlin – charles-allen Oct 27 '18 at 03:02
  • Both LayoutInflater.from(getContext()) and getActivity().getLayoutInflater() are working. – Ahmed Awadallah Dec 10 '18 at 09:21
1

It looks like this is fixed in Fragment 1.2.3: https://developer.android.com/jetpack/androidx/releases/fragment#1.2.3.

The docs do use requireActivity().getLayoutInflater() rather than just getLayoutInflater however so it still might not be recommended.

seadowg
  • 147
  • 8
1

You should use LayoutInflater.from(getContext()).

If you are using viewbindings you can call it like this:

binding = FragmentOtpDialogBinding.inflate(LayoutInflater.from(getContext()));

Prince
  • 20,353
  • 6
  • 39
  • 59