49

Is it possible to have an event when the FragmentTransaction is completed ?

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment).commit();

In fact, I use a Drawer for my application and I would like to trigger invalidateOptionsMenu(); when the transaction is completed to change the menu of my action bar.

lopez.mikhael
  • 9,943
  • 19
  • 67
  • 110

8 Answers8

60

You don't need to wait for the fragment transaction to complete, You can call

getSupportFragmentManager().executePendingTransactions();

after your commit() function call.

This will ensure that the transaction is complete.

Eldhose M Babu
  • 14,382
  • 8
  • 39
  • 44
  • 10
    My problem is not whether my transaction went well but to know when it is finished. Otherwise, there is a gap between the display of my view and change the menu bar of my action. – lopez.mikhael Nov 01 '13 at 10:16
  • The transaction will be completed forcefully when you call executePendingTransactions..how ever, it will take some time for the view to be loaded. To find out that, use a static function and call it from the onResume of your fragment. – Eldhose M Babu Nov 01 '13 at 12:04
  • 2
    I think this is a valid answer, even if it's not "event" per-se. executePendingTransactions() will *block* until the transaction is complete, and the next command after it will be invoked on completion of the transaction, just as an event would, and even without the overhead of event listener. – Amir Uval May 07 '14 at 07:39
  • 10
    This is not accurate, while adding a fragment after the **commit** and **executePendingTransactions** is returned the fragment stack has the added fragment, while removing or replacing a Fragment and after **commit** and **executePendingTransactions** is called, the removed fragment is still in the stack until a later time. It makes sense for UX reasons to remove and destroy the fragment later, however this is not the right way to get a transaction completed event! – TacB0sS May 07 '15 at 18:48
  • I didn't like this answer, but I realized I could use a workaround with it by putting an event using EventBus right after the call to `executePendingTransactions()`, and have my fragment listen for that event, and if it meets the criteria for deletion, then it can pop itself by calling `popFragment()` on its fragment manager. (I was trying to put that `popFragment()` code in onResume() if its model data did not exist, but it was giving the `IllegalStateException: FragmentManager is already executing transactions` error.) I basically made my own "Event" for when it was a completed transaction. – Rock Lee Mar 09 '17 at 20:20
13

Hei! Try this:

private OnBackStackChangedListener backStackListener =  new OnBackStackChangedListener() {

    @Override
    public void onBackStackChanged() {
        String name = "";
        int position = getSupportFragmentManager().getBackStackEntryCount();
        if(position!=0){
           FragmentManager.BackStackEntry backEntry=getSupportFragmentManager().getBackStackEntryAt(position-1);
           name=backEntry.getName();


        }
        if(position==0){
            mainActionBar();
        }
        else if(name=="someWord"){
            mainActionBar2();
        }
        else{
            mainActionBar3();
        }

    }
};
 getSupportFragmentManager().addOnBackStackChangedListener(backStackListener);

And in Transaction add tag to backStack like this:

getSupportFragmentManager().beginTransaction()
                .replace(R.id.main, SomeFragment.newInstance(some argument))
                .addToBackStack("someWord").commit();
Mikelis Kaneps
  • 4,576
  • 2
  • 34
  • 48
12

Too late but this may help (putting here for someone may use):

....
fragmentTransaction.replace(R.id.contentFrame, fragment);
fragmentTransaction.runOnCommit(new Runnable() // be carefull on this call. check documentation!!
{
    @Override
    public void run()
    {
        ... do something...  // this will  run after fragment's on resume. you can check.
    }
});
fragmentTransaction.commit();

please check runOnCommit() method restrictions!

Engin OZTURK
  • 2,065
  • 2
  • 21
  • 13
6
@Override
public void onResume() {
    super.onResume();
    getActivity().invalidateOptionsMenu();
}

When the FragmentTransaction is completed, the life cycle methods of the Fragment will be called, like onResume()

FYI, fragment can has its own menu, see http://developer.android.com/reference/android/app/Fragment.html#setHasOptionsMenu(boolean)

JIE WANG
  • 1,875
  • 1
  • 17
  • 27
3

You can use the advice given in this answer --- run the code you need after the transaction completes from the onAnimationEnd method.

For this to work, you need to set an animation on the FragmentTransaction using e.g.

transaction.setCustomAnimations(R.anim.slide_in_left,
                                R.anim.slide_out_right);
Community
  • 1
  • 1
Mark Minto
  • 101
  • 1
  • 5
1

You could consider using commitNow() instead of commit() and then you can be sure the transaction has finished. Of course its a matter of the complexity of the transaction if you should do it or not.

UriB
  • 111
  • 1
  • 6
0

i think i respond to your question so late but it could help someone who want the same solution :

ft.getLifecycle().addObserver(new LifecycleEventObserver() {
                 @Override
                 public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
                     if(event.getTargetState() == Lifecycle.State.RESUMED){
                         new Handler().postDelayed(new Runnable() {
                             @Override
                             public void run() {
                                invalidateOptionsMenu();
                             }
                         }, 500);
                     }
                 }
             });
-3

how about this method:

FragmentManager fm = ...;
fm.beginTransaction().add(xxx, FRAGMENT_TAG).commit();
handler.obtainMessage(FRAGMENT_COMMIT_FINISHED).sendToTarget();

when the commit() finished, you can get the event of FRAGMENT_COMMIT_FINISHED

WuHaojie
  • 105
  • 1
  • 7