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
.