3

I have been trying to solve a problem that is driving me nuts for ages. I have an app with one Activity that shows different screens by dynamic fragment exchange, ie the usual

getFragmentManager().beginTransaction().replace(R.id.fragementContainer, new SomeFragment()).commit();

This works great on my Nexus 4, Nexus 5, Nexus 7 2012, Nexus 7 2013, Moto G 1st gen etc. Mostly everything except Samsung devices (SGS5, SGS6). On these devices, sometimes (rarely, but not rarely enough) the replace() call seems to be misinterpreted as an add() call and the new fragment appears on top of the previous one.

I have tried replicating the bug but there doesn't seem to be any pattern to it. Since I get no error messages anywhere, I can't really troubleshoot it.

Antonis427
  • 1,012
  • 15
  • 22
  • 3
    I've seen a lot of bizarre, intermittent bugs on Samsung devices. Stuff like crashes due to a missing permission that the app clearly does have, else it would have crashed the other 999 out of 1000 times. My gut instinct says they're over-optimizing for their multi-core CPUs and running into race conditions. – Kevin Krumwiede Jul 27 '15 at 19:23
  • Yeah this is probably a Samsung thing. Try using `remove()` and `add()` instead of `replace()`. – Lamorak Jul 27 '15 at 19:44
  • @Lamorak: I thought about it but the problem with that approach is that I have to know which fragment was previously loaded so that I can call remove() on that, which means a lot of mess with if-statements in the code that I'd like to avoid. – Antonis427 Jul 27 '15 at 19:50
  • I don't understand. Your statement "...misinterpreted as an add() call and the new fragment appears on top of the previous one.". Isn't replace() suppose to show the new fragment on top of previous? – The Original Android Jul 27 '15 at 20:31
  • As far as I know, a replace() call first removes the previous fragment and then adds the new one, which means that the old fragment does not exist behind the new one. – Antonis427 Jul 27 '15 at 20:33
  • Yes, [`replace()` docs](http://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#replace%28int,%20android.support.v4.app.Fragment,%20java.lang.String%29) state that it actually is similar to `remove()` and `add()`. – Lamorak Jul 27 '15 at 20:49
  • @Antonis427, Technically replace() does not remove the previous fragment. The document states replace does "Replace an existing fragment that was added to a container", from link http://developer.android.com/reference/android/app/FragmentTransaction.html#replace(int, android.app.Fragment, java.lang.String). So this states it removes the fragment using the container view ID. This info may give you a hint on what to do. I normally use replace() with the same container ID, and never manage my own fragments. I use AddtoBackStack() for that. – The Original Android Jul 27 '15 at 21:26

2 Answers2

3

This is the why I always use support libraries. Source code is within your project and has not been modified by third parties. Are you already using support package?

Mimmo Grottoli
  • 5,758
  • 2
  • 17
  • 27
1

This might very well be caused by some Samsung "optimizations". The only thing I can advise is to use remove() and add() instead of replace(). The implementation within FragmentTransaction is different so there is a chance this will behave differently.

You can actually remove the fragment easily because it has the same id as the container. Try this:

FragmentTransaction transaction = fragmentManager.beginTransaction();

Fragment oldFragment = fragmentManager.findFragmentById(R.id.container);
if (oldFragment != null) transaction.remove(oldFragment);

transaction.add(R.id.container, new Fragment(), "tag").commit();
Lamorak
  • 10,957
  • 9
  • 43
  • 57
  • Thanks for the suggestion and the idea of using the findFragmentById() method, which I never thought of using! I tried it, let's see what happens! – Antonis427 Jul 28 '15 at 08:23