What I am attempting is to wait in my main activity until my fragment finishes, so I can execute code without causing problems in the fragment. I have tried many methods and can't get a solution. Heres some of my code from my main activity:
if (null == savedInstanceState) {
getFragmentManager().beginTransaction()
.replace(R.id.container, CameraFragment.newInstance())
.commit();
}
This will run a fragment that takes a picture and saves it.
The problem i'm having is, for example, I want to wait until this fragment has finished, then execute more code from my main activity. I can't find a working solution.
Edit: Solved, see the answer. Thanks!
Create a method on your activity, to run when your fragment is complete
Implement the OnResume method on the fragment like this:
#Override
public void onResume() {
super.onResume();
((NameOfActivity) getActivity()).afterFragmentComplete();
}
You're confused. You don't run a fragment. You display it. There is no way of "waiting for a fragment to complete" because fragments don't have the concept of completion. If you have a fragment that does something then wants to notify the activity to do something (which may include getting rid of that fragment) the way to do it is to pass the fragment an callback to the Activity that it will call when needed (such as when the user presses a save button).
Related
I have an Activity with a cancel button that sends people back to a
a starting Fragment:
cancelButton.setOnClickListener{
supportFragmentManager.beginTransaction().replace(R.id.fragment_holder,StartFragment.newInstance()).commit()
}
I would like to clear the entire Fragment backstack when this starting Fragment is returned to. I am attempting to do this in the Fragment's onStart method:
while (activity!!.supportFragmentManager!!.backStackEntryCount > 0) {
activity?.supportFragmentManager?.popBackStackImmediate()
}
Doing this throws the common java.lang.IllegalStateException: FragmentManager is already executing transactions error when the cancel button is pressed, but even after reading about other people's problems, I still can't figure out how these transactions work and what is happening to cause this error. The fragments are contained within a FrameLayout.
after replace and before commit, do the pop operation and it should work.
The Scene
I have an activity that houses 2 fragments .
Activity A is launched.
Fragment B completely takes over the activity A (UI wise).
Here depending on the operation , Fragment C launches and takes over the whole UI
The Target
I want to be able to know when a user presses back from Fragment C , and lands back on fragment B .
The Problem.
We all know that we CANNOT use the onResume override in the Fragment B , because this onResume is closely coupled with the Activity's lifecycle. If there was an override like onResume in Fragment B , it would have really helped my case. I know that the Fragment B is not onPaused when Fragment C overtakes it , so I am aware that onResume like strategy wont work .
The Solution
I think I can attach a callback onBackPressed in Activity A . Something like .
Psuedo Code
private onBackPressed()
{
if (currentFragment == Fragment C) {
FragmentB = findFragmentB();
//call custom method written in FragmentB
FragmentB.onBackPressed();
} else {
super.onBackPressed();
}
}
Before I proceeded , is this the right direction to move in ?
Exactly,,, if there is most suitable and easy solution for this problem. i think you should continue with this. I find out other ways but this was better and easy then others
Something alone the lines of this should work
BaseFragment currFrag = (BaseFragment) manager.findFragmentById(R.id.fragmentname);
currFrag.onFragmentResume();
Not much to explain here, onFragmentResume literally calls onResume of the fragment.
I'm having an issue of having two instances of the same fragment being attached to the activity. I have ActivityA attaching FragmentA on onCreate. When I leave the app while being on this Activity, browse other apps for a while, and return to the app, I see that the system is trying to re-create the activity. My log shows the code from the Fragment being ran TWICE. My guess is the Fragment is already attached but then the Activity attempts to create a new instance of FragmentA.
What happens to the Activity/Fragment when the system removes them from memory, and what's the best way to handle this? Any links would be helpful.
Will provide code if needed.
The best way to handle this is to check in your onCreate() method if your activity if being recreated from a previous state or not. I'm assuming you add your fragment on the onCreate() method of your activity. You can do something like this:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState == null)
{
// Add the fragment here to your activity
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.content, new YourFragment());
ft.commit();
}
}
By doing this, you are basically saying that if a previous state is not found, you add your fragment. Otherwise you automatically get back the fragment that already exists.
Here is my code
public void changeFragment(Fragment contentFragment, Fragment lastFragment, int resourseID,int animationType, boolean addToStack) {
if (contentFragment != lastFragment) {
mContentFragmentTransaction = getFragmentManager().beginTransaction();
FragmentTransactionExtended fragmentTransactionExtended = new FragmentTransactionExtended(this, mContentFragmentTransaction,lastFragment,contentFragment, resourseID);
fragmentTransactionExtended.addTransition(animationType);
mContentFragmentTransaction.replace(resourseID, contentFragment);
if (addToStack) {
mContentFragmentTransaction.addToBackStack(null);
}
mContentFragmentTransaction.commit();
}
}
The problem is, everytime I changeFragment using this method, the fragment's oncreate will fire multiple times, first time, it runs once, second time twice , third time three times, hope someone know what's happening here.
addToBackstack creates a snapshot of your fragments state. Which means when you press the back button, you are actually reverting to the last state that addToBackstack was called on.
You have to call replace on the container that has the fragment, not the fragment itself. So instead of calling replace(R.id.dashboard, fragment) it should be replace(R.id.dashboards_container, fragment).
have you tried to use an other method, like remove(), then do an add(). or anything similar? some people say's replace() method does not always behave correctly.
If the state of the activity has already been saved its no longer safe to call commit. You must call commitAllowingStateLoss() instead.
Even if you use replace or remove calls you can't do this. Only work around I have found is to create a new instance of a fragment and add it every time. Once you remove or replace a fragment it is best to drop all of your references to it so the GC can take care of it.
regards maven
My application usually add and then remove the same fragment many times. Below is how I do this:
Add fragment
if (mHomeFragment == null)
{
mHomeFragment = new HomeFragment();
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
getSupportFragmentManager().beginTransaction().add(R.id.dummy, mHomeFragment).commit();
}
}, getResources().getInteger(R.integer.transition_duration));
}
else
{
getSupportFragmentManager().beginTransaction().add(R.id.dummy, mHomeFragment).commit();
}
Remove fragment
getSupportFragmentManager().beginTransaction().remove(mHomeFragment).commit();
Problem is, sometime my app has crashed when navigate from the activity contains that fragment (HomeFragment) to another activity. I tried to figure out why but still no way. I have no full error-log here because this error doesn't happen often, but the error is same like this https://android.googlesource.com/platform/frameworks/support/+/5506618c80a292ac275d8b0c1046b446c7f58836%5E!/:
IllegalStateException: Failure saving state......active HomeFragment{419494f0} has cleared index: -1
Does anyone see any problem with my code or just know how to fix this error, please help me. Thank you all in advance.
It sounds like the runnable might be running after the activity was paused or finished. Just make sure to call handler.removeCallback on the activity onPause method to avoid the callback to the activity once it's done.
If you need to swap fragments often, you can use the FragmentTransaction hide and show methods so you avoid the initialization overhead.