Issue
I have a case where I have two clickable items in a fragment. Item A detaches the current fragment from the current activity, and attaches a new fragment. Item B causes some UI updates. My problem is, if I click on both of them in quick succession, the app crashes. I get a NullPointerException in the UI updates because apparently the fragment has already been detached from item A. A more visual representation of the log:
- Click item B
- Click item A shortly thereafter
- Item A causes the current fragment to detach, and eventually causes onDestroyView to be called.
- Item B attempts to update the UI about 150ms later, but the UI elements are now null because onDestroyView has already executed, causing a NPE.
I'm using a Nexus 4 running 4.2.2. I'm using Dagger to do dependency injection, which I thought could be the source of the issues, but I'm seeing similar edge cases throughout my app where two things can be clicked on almost simultaneously and the crashes sometimes happen with things that aren't injected. In each case, both actions will happen in a seemingly undefined order, which causes weird behavior and crashes.
Is there a way to stop all subsequent or in flight events in onStop or onDestroyView? Or do I need to add an isDetached() check to every one of my UI listeners? I also tried detaching all of my listeners in onDestroy, which eliminated some, but not all of the crashes. It seems that I'm having a similar issue to this unanswered question: Fragment's OnClickListener called after onDestroyView.
Solution
It is not possible to give exact solution to the problem without seeing your actual implementation, but here is what I'd do:
Pass the instance of the fragment to the method where I am doing the UI update and check if the fragment is currently being removed, is added or was not already detached from the UI (or any combination of these) before actually attempting the update. Example:
private static void updateUi(MyFragment fragment, Object param) {
if (fragment.isRemoving() || fragment.isDetached() || !fragment.isAdded()) {
return;
}
// Update the UI
}
Hope this helps.
Answered By - ozbek
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.