I've been working for several months in an app. The version uploaded to the playstore works fine. Recently, doing some improvements, the whole app has started to work in a very strange way.
If you swith between fragments, after a while it does not inflate properly the fragments, putting always the content of the first one. So, if you switch the fragment, the action bar changes but the content is always the same (and you cannot interact with it).
Here is a quick video of the error https://streamable.com/9exa
I am going crazy as there is no log or trace whatsoever.
I am using the usual way of swithing fragments and the most intriguing part is that at the beginning everything works ok:
Fragment fragment = getSelectedFragment(index); // returns the desired fragment
FragmentManager fragmentManager = getFragmentManager();
//Pop backstack
for(int i = 0; i < fragmentManager.getBackStackEntryCount(); ++i) {
fragmentManager.popBackStack();
}
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(null)
.commit();
Do anyone has any kind of idea what could be happening here? Thanks!
edit: I also have tried to clear the backstack in case it was the problem, but it doesn't change anything
solved: As I explain in my answer, I have discovered that is a problem related to a SwipeRefreshLayout. More information about this problem can be found at When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work
Ok, I found out the problem.
It seems that a SwipeRefreshLayout was the one causing all the problems. One of my fragments was using it, and after switching fragments a couple of times it gets stuck.
Removing it, or disabling it setEnabled(false) solves all the problems.
I hope it will help to anyone that is having the same problem!
Another thread in SO that refers to the same problem: When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work
What fragments are you using?
I had some strange behaviour using framework fragments, and i switched to V4 and everything worked fine
Please check this link: FragmentManager popBackStack doesn't remove fragment
I am using the following code in my activity for switching between fragments and it is working fine. My app's minSdkVersion is 15.
private void setFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.commit();
}
Related
EDIT: I want to solve problem of duplicating fragment in view Pager, removing them isn't the best solution.
I have a problem with FragmentManager in my app. Every time when I click "Wykłady teoretyczne" or "Wykłady popularnonaukowe" on Navigation Drawer my app is creating new fragment ScheduleFragment() which contains ViewPager and in SchedulePagerAdapter app is creating new 3 fragments (ScheduleEventFragment()) to swipe them in ScheduleFragment. My problem is that FragmentManager doesn't remove old ScheduleEventFragments, for all the time it keeps them in memory. How can I fix this problem?
I have my project on GitHub, please check it.
There you have screen from debuging
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.remove(R.id.container,fragment,optionalTag);
fragmentTransaction.commit();You can also detach or replace
Always check if fragmemt.isAdded() and then only add the fragment if not.
I have a strange behaviour with the Android UI. At the beginning all works fine but after a minute the fragment always gets blank when replacing it with the FragmentManager. When reopening the app all looks fine again. I am using an AppCompatActivity does someone know a solution for this?
This is my replace code
var fragmentTransaction = FragmentManager.BeginTransaction();
fragmentTransaction.Replace(Resource.Id.frameLayout1, nextFrag).AddToBackStack("div_overview").Commit();
Edit:
I open the first fragment by using the following code in the MainActivity :
SupportFragmentManager.BeginTransaction().Replace(Resource.Id.frameLayout1, fragments[1]).Commit();
This Fragment can open other fragments by button click. For this i am using
var fragmentTransaction = FragmentManager.BeginTransaction(); fragmentTransaction.Replace(Resource.Id.frameLayout1, nextFrag).AddToBackStack("div_overview").Commit();
This behaviour only happens after some time (mostly after the screen has been darken). The first transactions are working without any problems...
Thank you in advance!
I have a bug with replacing fragments inside FrameLayout container.
When app is started first time everything is Ok but when I hide app and then resume it fragments start overlap each other when FragmentTransaction.replace method is called
I've seen almost all stackoverflow questions about such issues but I can't resolve this issue
Code:
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
Add initial fragment:
getSupportFragmentManager().beginTransaction()
.add(R.id.frame, RequestFragment.newInstance(), REQUEST_FRAGMENT_TAG)
.commit();
Replace:
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
switch (menuItem.getItemId()) {
case R.id.request:
ft.replace(R.id.frame, RequestFragment.newInstance(), REQUEST_FRAGMENT_TAG);
ft.commit();
return true;
case R.id.finished:
ft.replace(R.id.frame, FinishedFragment.newInstance(), FINISHED_FRAGMENT_TAG);
ft.commit();
return true;
case R.id.questions:
ft.replace(R.id.frame, QuestionsFragment.newInstance(), QUESTIONS_FRAGMENT_TAG);
ft.commit();
return true;
default:
return true;
}
Difficult to say as your code provides no context as to when it is run but I suspect the issue is when you are adding your initial fragment.
You are calling add instead of replace which will just add the new fragment on top of any existing ones. It is perfectly fine to use replace even if the container does not yet contain anything.
Fragments survive in the FragmentManager and are automatically re-attached to their container when the Activity restarts. The correct procedure is to check for an existing Fragment before adding a new one.
Add initial fragment
Fragment f=getSupportFragmentManager().findFragmentById(R.id.frame);
if (f==null) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, RequestFragment.newInstance(), REQUEST_FRAGMENT_TAG).commit();
}
Also, it is helpful to make use of logging getSupportFragmentManager().getFragments().size(); whilst you are debugging. It lets you know how many fragments are currently in the FragmentManager and can highlight potential issues in your code. For example, if your count goes up every time you rotate the device, you are adding fragments and not checking for existing ones.
try to use FragmentTransaction.commitAllowingStateLoss() instead of using commit()
This sometimes happens because of the fragment background. Try setting solid background to all fragments in the stack so it's not empty or set to #null.
I wasn't calling the commit method at the end.
I am used to developed my applications fragments I have one problem
I am replacing fragments like
A -->B --> C --> D -->E -->F
How can i return back like
A <--B <-- C <-- D <--E <--F
I am using code like
getActivity().getFragmentManager().popBackStack();
this worked fine but some times closed app without cross
is there any solution i dnot how to slove the problem due have any idea please guide me
Advance thanks all``
With no code available I just post what it's working for me:
when switching from a Fragment to another i use this (if you aren't using the support libraries you have to remove the 'Support' prefix):
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.fragmentContainer,
MyFragment.newInstance());
transaction.addToBackStack(null);
transaction.commit();
The addToBackStack adds the fragment to the backstack... so when you press back button the previous fragment will pop up.
Hope it helps.
If it helps, what I want is similar to what is done in this google tutorial
But there a fragment is created prior to the transition. If I do that the transition works fine; but I can't use this approach
=====
Aiming to API 7+ I am just trying to have one Fragment visible in the whole screen and using a button (a drawn button, with an onTouch event) then alternate to a second fragment and viceversa.
But I either get a blank screen when I replace the first fragment with the second, or if I use fragmentTransaction.show and fragmentTransaction.hide; I can switch two times before I get blank screen. I dont want to have on backstack.
I am creating the fragments in MainActivity's onCreate:
DiceTable diceTable = new DiceTable();
Logger logger = new Logger();
fragmentTransaction.add(diceTable, DICETABLE_TAG);
fragmentTransaction.add(logger, LOGGER_TAG);
fragmentTransaction.add(R.id.fragment_container, logger);
fragmentTransaction.add(R.id.fragment_container, diceTable);
Then on one method (called from the fragments) I do the switch:
Logger logger = (Logger)fragmentManager.findFragmentByTag(LOGGER_TAG);
DiceTable diceTable = (DiceTable)fragmentManager.findFragmentByTag(DICETABLE_TAG);
if (diceTable.isVisible()) {
fragmentTransaction.replace(R.id.fragment_container, logger);
fragmentTransaction.commit();
fragmentTransaction.hide(diceTable);
fragmentTransaction.show(logger);
}
else if (logger.isVisible()) {
fragmentTransaction.replace(R.id.fragment_container, diceTable);
fragmentTransaction.commit();
fragmentTransaction.hide(logger);
fragmentTransaction.show(diceTable);
}
This is not how I should do this?
Blank screen when replacing fragments
Try to initialize fragments in that way:
private void initFragments() {
mDiceTable = new DiceTable();
mLogger = new Logger();
isDiceTableVisible = true;
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragment_container, mDiceTable);
ft.add(R.id.fragment_container, mLogger);
ft.hide(mLogger);
ft.commit();
}
And then flip between them in that way:
private void flipFragments() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
if (isDiceTableVisible) {
ft.hide(mDiceTable);
ft.show(mLogger);
} else {
ft.hide(mLogger);
ft.show(mDiceTable);
}
ft.commit();
isDiceTableVisible = !isDiceTableVisible;
}
You are combining two different methods of changing which Fragment is shown:
Calling replace() to replace the contents of the container with a different Fragment
Calling hide() to remove a Fragment, then calling show() to show another Fragment.
Pick one method and stick with it. The Building a Flexible UI guide uses just the replace() method, so I would start by trying to remove all of your calls to show() and hide().
Also see Android Fragments: When to use hide/show or add/remove/replace? for a quick summary of when it might be beneficial to use hide/show instead of replace.
In case anyone has tried all of the already suggested answers and is still facing the issue, like I was a few moments ago, the problem may come from a different source than your fragments.
In my case, I was switching between fragments correctly, but the reason for the blank screen was that in each new fragment I was trying to asynchronously load images by starting a new Thread every time (something a bit like this) instead of the recommended AsyncTask, or better yet the newSingleThreadExecutor, since AsyncTask is deprecated.
I disturbed the background enough that the fragment was just not showing up unless I navigated to a different app then back.
So unless your mistake is similar to mine my suggestion might be kind of vague but try to see if anything is happening in your fragment that may be intensive on the resources (commenting out different pieces of code may help in investigating this).