TL;DR用(简单的方式)包裹你的navigate
电话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);
它甚至变得有点短。该代码在发生崩溃的确切位置进行了测试。没有再体验过,其他导航也会使用相同的解决方案,以进一步避免同样的错误。
欢迎任何想法!
究竟是什么导致了崩溃
请记住,当我们使用方法时,我们在这里使用相同的导航图、导航控制器和后台堆栈Navigation.findNavController
。
我们总是在这里得到相同的控制器和图形。当UI 尚未更新时navigate(R.id.my_next_destination)
,图形和 back-stack几乎立即发生变化。只是不够快,但没关系。在回栈改变后,导航系统接收到第二个navigate(R.id.my_next_destination)
调用。由于 back-stack 发生了变化,我们现在相对于堆栈中的顶部片段进行操作。顶部片段是您使用 导航到的片段R.id.my_next_destination
,但它不包含下一个带有 ID 的其他目的地R.id.my_next_destination
。因此,您会IllegalArgumentException
因为片段一无所知的 ID 而得到。
这个确切的错误可以在NavController.java
method中找到findDestination
。