Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onClick or onItemClick while paused results in "IllegalStateException: Can not perform this action after onSaveInstanceState"

I have a TabActivity which hosts 5x FragmentActivity. Several of these contain buttons or lists that, in their onClick() or onItemClick(), create and push a new fragment.

For the most part, this works fine, but if things are being a bit unresponsive, or a tester does something silly (press-and-hold a button or list item, use a different finger to switch tabs, then release the button/list -- 100% reproducible), I get the click event well after the activity has been paused and saved. See log snippet:

10-30 17:05:16.258  3415  3415 D BKC DEBUG: More.onSaveInstanceState()
10-30 17:05:16.258  3415  3415 D BKC DEBUG: MoreFragment.onPause()
10-30 17:05:17.309  3415  3415 D BKC DEBUG: MoreFragment.onItemClick()

After reading this article and various StackOverflow questions about fragment state loss, I don't see a good answer to how to fix this.

  • Using commitAllowingStateLoss() (unconditionally) is a workaround that could hide real bugs.
  • I'm not sure that unregistering OnClickListeners and OnItemClickListeners in onSaveInstanceState would 100% prevent this, and it's kind of a PITA to do that for every button in every fragment.
  • Someone suggested checking the relevant fragment's isAdded(), but I can confirm that doesn't work.
  • I could set a flag in onSaveInstanceState() and onRestoreInstanceState() and check that in onClick(), but again, that's just a kludge. EDIT: Oh, fragment doesn't have onRestoreInstanceState(), but I can twiddle the flag in onResume() or whatever.

Is there a correct fix for this that I'm missing, or should I just go with my kludge of choice?

like image 624
benkc Avatar asked Oct 31 '13 00:10

benkc


1 Answers

After thinking about it some more, I believe that commitAllowingStateLoss() is in fact the right answer for this case. We know that we are in the onClick() or onItemClick() handler, so if state loss could occur, we know it's because of this hole that allows click events through after the onSaveInstanceState().

In my casual testing, the new fragment will in fact pop up when you go back to the relevant tab, since nothing was actually torn down. That's a bit surprising to the user, but probably acceptable for this edge case.

like image 103
benkc Avatar answered Sep 30 '22 00:09

benkc