TL; DRnavigate
用try-catch
(简单的方式)将电话换行,或确保navigate
在短时间内仅打一个电话。这个问题可能不会消失。在您的应用中复制更大的代码段,然后尝试一下。
你好。基于以上几个有用的回答,我想分享我的可以扩展的解决方案。
这是导致我的应用程序崩溃的代码:
@Override
public void onListItemClicked(ListItem item) {
Bundle bundle = new Bundle();
bundle.putParcelable(SomeFragment.LIST_KEY, item);
Navigation.findNavController(recyclerView).navigate(R.id.action_listFragment_to_listItemInfoFragment, bundle);
}
轻松重现此错误的一种方法是用多指点击项目列表,其中每个项目的点击都会在导航到新屏幕的过程中解析(基本上与人们所指出的相同-在非常短的时间内两次或更多次单击) )。我注意到:
- 第一次
navigate
调用总是可以正常工作;
- 该
navigate
方法的第二次及所有其他调用在中解决IllegalArgumentException
。
在我看来,这种情况可能经常出现。由于重复代码是一种不好的做法,因此影响一个观点总是一件好事,我想到了下一个解决方案:
public class NavigationHandler {
public static void navigate(View view, @IdRes int destination) {
navigate(view, destination, /* args */null);
}
/**
* Performs a navigation to given destination using {@link androidx.navigation.NavController}
* found via {@param view}. Catches {@link IllegalArgumentException} that may occur due to
* multiple invocations of {@link androidx.navigation.NavController#navigate} in short period of time.
* The navigation must work as intended.
*
* @param view the view to search from
* @param destination destination id
* @param args arguments to pass to the destination
*/
public static void navigate(View view, @IdRes int destination, @Nullable Bundle args) {
try {
Navigation.findNavController(view).navigate(destination, args);
} catch (IllegalArgumentException e) {
Log.e(NavigationHandler.class.getSimpleName(), "Multiple navigation attempts handled.");
}
}
}
因此,上面的代码仅在一行中更改:
Navigation.findNavController(recyclerView).navigate(R.id.action_listFragment_to_listItemInfoFragment, bundle);
对此:
NavigationHandler.navigate(recyclerView, R.id.action_listFragment_to_listItemInfoFragment, bundle);
它甚至变得更短。该代码已在发生崩溃的确切位置进行了测试。不再体验,将对其他导航使用相同的解决方案,以进一步避免相同的错误。
任何想法都欢迎!
究竟是什么导致撞车
请记住,这里使用method时,我们使用相同的导航图,导航控制器和后堆栈Navigation.findNavController
。
我们总是在这里得到相同的控制器和图形。何时navigate(R.id.my_next_destination)
调用图形和后堆栈几乎立即更改,而UI尚未更新。只是不够快,但是没关系。更改后堆栈后,导航系统会收到第二个navigate(R.id.my_next_destination)
呼叫。由于后堆栈已更改,因此我们现在相对于堆栈中的顶部片段进行操作。最上面的片段是您使用导航到的片段R.id.my_next_destination
,但是它不包含ID为的下一个其他目标R.id.my_next_destination
。这样,您就可以得到IllegalArgumentException
该片段一无所知的ID。
这个确切的错误可以在NavController.java
method中找到findDestination
。