0

My Navigation graph has two destinations, a Fragment and a DialogFragment. The Fragment contains a Button that navigates to the DialogFragment when pressed.

Everything works as expected, except if I click the button very quickly. Doing so can trigger a

IllegalArgumentException: navigation destination com.example.app:id/show_dialog is unknown to this NavController

To fix this, I ensure that the current destination is the Fragment containing the show_dialog action:

val navController = findNavController()
val currentDest = navController.currentDestination?.id

if (currentDest == R.id.test_fragment) {
    navController.navigate(TestFragmentDirections.showDialog())
}

Making this change appears to fix the issue. However, I would like to know:

Why is it necessary to wrap the navigate call with a conditional statement in this situation?

  • 1
    you could avoid all this talk with just a `try/catch/finally` block – coroutineDispatcher May 31 '19 at 09:37
  • Yeah, but I'm interested to know *why* I have to do this check at that particular time. I plan on doing a lot of work with Jetpack components in the future, so it's good to know. –  May 31 '19 at 09:39
  • I see what you mean now, I can use a `try/catch` to help me get to the bottom of things. Will do. Thanks. –  May 31 '19 at 11:10
  • i will use an answer for that – coroutineDispatcher May 31 '19 at 11:41
  • 1
    Check this [issue ticket](https://issuetracker.google.com/issues/118975714) to see Android's answer for the problem – Sanlok Lee May 31 '19 at 21:23
  • Thanks, Sanlok. I guess what's happening is I'm clicking the Show Dialog button fast enough that it registers two clicks. The fragment is notified of the first click and navigates to the dialog. It is still notified of the second click because it is STARTED while the dialog is on screen? –  May 31 '19 at 21:59
  • According to that issue ticket, it's fixed in `Fragment 1.1.0alpha01`, but I'm seeing my test project has a transient dependency on `Fragment 1.1.0alpha09` –  May 31 '19 at 22:00
  • Yes I can also confirm that this is not really 100% fixed. I think your theory about multiple click being registered is true. I have also found this [thread](https://stackoverflow.com/questions/51060762/java-lang-illegalargumentexception-navigation-destination-xxx-is-unknown-to-thi?noredirect=1&lq=1) discussing about the solution. Addition to these, if you have only one button in each screen, I think you can also try implementing debounced click listeners. – Sanlok Lee May 31 '19 at 22:53

2 Answers2

0

Your question is just based on the Android inside Architecture and is also dependent on the hardware performance. Just wrap it in a try/catch block:

try{
  findNavController().navigate(TestFragmentDirections.showDialog())
}catch(e: IllegalArgumentException){
    e.printStackTrace
}
coroutineDispatcher
  • 7,718
  • 6
  • 30
  • 58
  • You're right, I'll have to just accept it until I become more familiar with the inner workings. Thank you. –  Jun 04 '19 at 04:03
0

You might be getting IllegalArgumentException because if you see showDialog() method, you will find implementation as below:

public void show(FragmentManager manager, String tag) {
    mDismissed = false;
    mShownByMe = true;
    FragmentTransaction ft = manager.beginTransaction();
    ft.add(this, tag);
    ft.commit();
}

I'll suggest to write your own showDialog menthod with below implementation:

fragmentManager.beginTransaction()
               .add(dialog, "TAG")
               .commitAllowingStateLoss();
Shrikant
  • 579
  • 1
  • 5
  • 21