Disclaimer: I've checked the documentation and since 2.1.0
the navigation components has supported Dialog Fragments. (https://developer.android.com/jetpack/androidx/releases/navigation#2.1.0)
I'm getting this error when trying to go from a DialogFragment
to my Start Destination
:
java.lang.IllegalStateException: Fragment PostDistressDialog{829f5d1} (bbbc4926-684b-491b-9772-e0f0ffebe0af)} not associated with a fragment manager.
PostDistressDialog
is a DialogFragment
called from JournalEntryFragment
(can be seen in map below) using the navigation component. PostDistressDialog
is not an inner class of JournalEntryFragment
. It is in a class of its own extending DialogFragment
public class PostDistressDialog extends DialogFragment implements ISaveDatabase {
...
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
if (getArguments()!=null) {
...
// Set up the Alert Dialog
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
alertDialog.setTitle(R.string.distressed_levels);
alertDialog.setMessage(R.string.distressed_how_feel_post);
// Inflate and set the layout for the dialog
View layout = View.inflate(getActivity(), R.layout.dialog_seekbar, null);
alertDialog.setView(layout);
....
// Add okay button
alertDialog.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Save post distress value in Journal Entry
mJournalEntry.setPostDistress(mTempDistressValue);
// Save to Journal Entry to database
// Check if journal entry empty
if(isJournalEntryEmpty(mJournalEntry)){
...
}
else{
// Give title if empty
if(mJournalEntry.getTitle().isEmpty()) {
....
// Save to database
new SaveDatabase(getContext(),PostDistressDialog.this).execute(mJournalEntry);
}
// Go to main menu
}
});
return alertDialog.create();
}
return null;
}
...
@Override
public void databaseSavingCompleted(){
NavHostFragment.findNavController(this).navigate(PostDistressDialogDirections.postDistressDialogToJournalListAction());
}
}
Where this
is public class PostDistressDialog extends DialogFragment
<dialog
android:id="@+id/postDistressDialog"
android:name="com.dgrullon.cbtjourney.dialogs.PostDistressDialog"
android:label="PostDistressDialog" >
<argument
android:name="postDistressDialogArguments"
app:argType="com.dgrullon.cbtjourney.pojo.JournalEntries"/>
<action
android:id="@+id/postDistressDialog_to_journalListAction"
app:destination="@id/journalList"
app:popUpTo="@id/journalList"
app:popUpToInclusive="true" />
</dialog>
AlertDialog automatically dismisses the Dialog (and hence, removes your DialogFragment
) when the callback you add to setPositiveButton
is fired. Because you're doing work asynchronously, your databaseSavingCompleted
method is called after the DialogFragment is destroyed, detached from the FragmentManager, and removed from the NavController - you're leaking a reference to your DialogFragment (as it would otherwise be garbage collected).
Therefore when NavHostFragment.findNavController(this)
fires, all hooks that would let it access the NavController
are already cleaned up.
If you don't want your button to immediately dismiss the dialog, you need to pass in null
to setPositiveButton()
and instead get a reference to the button after the dialog has been created by calling its getButton()
API and manually setting an OnClickListener
that would kick off your AsyncTask
(and disable the button to prevent it from being clicked more than once).