TL; DRnavigate
Aramalarınızı try-catch
(basit yol) ile tamamlayın veya navigate
kısa süre içinde yalnızca bir arama olacağından emin olun . Bu sorun muhtemelen ortadan kalkmayacak. Uygulamanızda daha büyük kod parçacığını kopyalayın ve deneyin.
Merhaba. Yukarıdaki birkaç yararlı yanıta dayanarak, genişletilebilecek çözümümü paylaşmak istiyorum.
İşte uygulamamdaki bu çökmeye neden olan kod:
@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);
}
Hatayı kolayca yeniden oluşturmanın bir yolu, her bir öğeye tıklamanın yeni ekranda gezinmede çözüldüğü öğeler listesine birden fazla parmakla dokunmaktır (temelde insanların belirttiği gibi - çok kısa bir süre içinde iki veya daha fazla tıklama) ). Onu farkettim:
- İlk
navigate
çağrı her zaman iyi çalışır;
- İkinci ve
navigate
yöntemin diğer tüm çağrıları çözülür IllegalArgumentException
.
Benim açımdan bu durum çok sık karşımıza çıkabilir. Kodun tekrarlanması kötü bir uygulama olduğundan ve bir etki noktasına sahip olmak her zaman iyidir çünkü bir sonraki çözümü düşündüm:
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.");
}
}
}
Ve böylece yukarıdaki kod bundan sadece bir satırda değişir:
Navigation.findNavController(recyclerView).navigate(R.id.action_listFragment_to_listItemInfoFragment, bundle);
buna:
NavigationHandler.navigate(recyclerView, R.id.action_listFragment_to_listItemInfoFragment, bundle);
Hatta biraz daha kısaldı. Kod, kazanın meydana geldiği yerde test edildi. Artık deneyimlemedi ve aynı hatayı daha fazla önlemek için diğer navigasyonlarda aynı çözümü kullanacak.
Herhangi bir düşünceye açığız!
Kazaya tam olarak ne sebep olur
Yöntemi kullandığımızda burada aynı gezinme grafiği, gezinme denetleyicisi ve arka yığınla çalıştığımızı unutmayın Navigation.findNavController
.
Burada hep aynı denetleyiciyi ve grafiği elde ederiz. Ne zaman navigate(R.id.my_next_destination)
grafiği ve arka yığını değiştirir denir neredeyse anında UI henüz güncellenmemiş ise. Yeterince hızlı değil, ama sorun değil. Arka yığın değiştikten sonra, navigasyon sistemi ikinci navigate(R.id.my_next_destination)
çağrıyı alır . Arka yığın değiştiğinden, artık yığındaki en üst parçaya göre çalışıyoruz. En üstteki parça, kullanarak gezindiğiniz parçadır R.id.my_next_destination
, ancak kimliğe sahip sonraki herhangi bir hedefi içermez R.id.my_next_destination
. Böylece IllegalArgumentException
parçanın hakkında hiçbir şey bilmediği kimlik sayesinde elde edersiniz .
Bu kesin hata NavController.java
yöntemde bulunabilir findDestination
.