This is onViewCreated
of My Fragment:
@Override
public void onViewCreated(@NonNull View view, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
NavHostFragment navHostFragment = (NavHostFragment) requireActivity().getSupportFragmentManager().findFragmentById(R.id.container);
binding.button.setOnClickListener(v -> {
if (navHostFragment != null) {
NavController navController0 = navHostFragment.getNavController();
navController0.navigate(MyFragmentDirections.actionMyFragmentToMessageDialog(
false,
R.drawable.ic_success,
"My Message 1",
R.string.yes,
R.string.no,
R.drawable.circle_yellow
));
}
});
if (navHostFragment != null) {
NavController navController1 = navHostFragment.getNavController();
NavBackStackEntry navBackStackEntry = navController1.getCurrentBackStackEntry();
if (navBackStackEntry != null) {
SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle();
MutableLiveData<String> liveData = savedStateHandle.getLiveData(Const.DIALOG_BTN_DATA);
liveData.observe(getViewLifecycleOwner(), btnData -> {
// savedStateHandle.remove(Const.DIALOG_BTN_DATA);
if (btnData.equals("btn_right")) {
Log.i(TAG, "Dialog Btn Clicked -----> btn_right");
NavController navController2 = navHostFragment.getNavController();
navController2.navigate(MyFragmentDirections.actionMyFragmentToMessageDialog(
false,
R.drawable.ic_success,
"My Message 2",
R.string.yes,
R.string.no,
R.drawable.circle_red
));
} else {
// Do Some Stuff
}
});
}
}
}
And this is the button onClickListener
of Dialog:
binding.btnRight.setOnClickListener(v -> {
NavHostFragment navHostFragment = (NavHostFragment) requireActivity().getSupportFragmentManager().findFragmentById(R.id.container);
if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
NavBackStackEntry navBackStackEntry = navController.getPreviousBackStackEntry();
if (navBackStackEntry != null) {
SavedStateHandle savedStateHandle = navBackStackEntry.getSavedStateHandle();
savedStateHandle.set(Const.DIALOG_BTN_DATA, "btn_right");
}
navController.navigateUp();
}
});
I need to show DialogFragment when another DialogFragment result received, but app crashes in statement navController2.navigate(MyFragmentDirections.actionMyFragmentToMessageDialog...
and I get the below error:
java.lang.IllegalArgumentException: Navigation action/destination com.example.app:id/action_myFragment_to_messageDialog cannot be found from the current destination
Can anyone help me to solve the problem and show DialogFragment in navBackStackEntry observer result of another DialogFragment using NavigationComponent?
Your issue is not related to usage of navController
. You can find its definition in Navigation Component documents.
So I avoid to describe them and want to focus on your code.
Action X
to Y
means you want navigate to Y
only from X
. In other words the last entry/destination in back-stack must be X
.
In your case when MyFragment
is shown, the back-stack is like:
[ MyFragment ]
and when you call getSavedStateHandle()
and start observing its savedState
means you're obsrving MyFragment
's savedState.
When you want to launch dialog with "My Message 1"
in button click listener, back-stack is still:
[ MyFragment ]
and after launching the dialog will be like:
[ MyFragment, MessageDialog ]
So when you getPreviousBackStackEntry
in dialog, it refers to MyFragment
and successfully set(Const.DIALOG_BTN_DATA, "btn_right")
on MyFragment
's savedState.
At this time the observer in MyFragment
will be triggered and try to launch dialog via actionMyFragmentToMessageDialog
with "My Message 2"
.
This action is from MyFragment
to MessageDialog
but the latest entry in back-stack is MessageDialog
(Not MyFragment). BOOOM
and navController.navigateUp()
will never invoke to pop dialog :D
show DialogFragment in navBackStackEntry observer result of another DialogFragment using NavigationComponent?
Your issue comes from restriction of local actions. So you should navigate by destination-id
s or deeplink
s or better one is GlobalActions
that provide safe-arg facilities.
I suggest global actions in this situation:
<action
android:id="@+id/action_global_messageDialog"
app:destination="@id/messageDialog" />
navController2.navigate(
MyGraphDirections.actionGlobalMessageDialog(
false,
R.drawable.ic_success,
"My Message 2"
R.string.yes,
R.string.no,
R.drawable.circle_red
));