How to notify your Fragment of different user navigation events

If you are using Android Fragments in your app, it can sometimes be useful to know when a user is navigation away from your fragment, so that you can act upon the users action, either by saving away data, asking the user for a confirmation, or what else.

Here I will describe three methods of registering navigation events.

Telling the Fragment that the back button has been pressed, through a reference to your fragment

If you would like to know that the user pressed the back button, you can get that information through a FragmentActivity.

Inside a FragmentActivity, we can override the onBackPressed method, and we can use this to notify the fragment that the user has pressed the back button. We can then act accordingly.

If we have an activity called DetailActivity:

public class DetailActivity extends FragmentActivity {

    private DetailFragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_note_detail);
        fragment = new DetailFragment();

        getSupportFragmentManager().beginTransaction()
            .add(R.id.detail_container, fragment).commit();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        fragment.backButtonWasPressed();
    }
}

And a fragment called DetailFragment:

public class DetailFragment extends Fragment {

    public DetailFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // ...
    }

    public void backButtonWasPressed() {
        saveDataBeforeExiting();
    }
}

We can use the onBackPressed method in our activity, to call the backButtonWasPressed method that we created in the fragment. There, we can do what we want to do, when the backbutton is pressed.

Telling the Fragment that the back button has been pressed, through an interface

As user pedro suggested in the comments, interfaces can be used for this kind of communication. There is an example of using interfaces on the Android developer website, the example is for Fragment to Activity communication, and for calling the fragment through a reference, like the code above here)
I built on that example when I created this interface example.

This is a simplified example, for when you know that the Fragment is always used with an activity.

  1. The DetailActivity creates an interface called Callbacks, containing one method called onBackPressedCallback.
  2. The overridden onBackPressed method gets called by the system when the user presses the back button, this method in turn calls the interface method
  3. The DetailFragment implements the interface method onBackPressedCallback, and now recieves a call from the DetailActivity everytime the back button gets pressed.
    The DetailFragment can then act on this event.

The DetailActivity with the interface and callbacks:

public class DetailActivity extends FragmentActivity {

    private DetailFragment fragment;

    private Callbacks mCallbacks;

    public interface Callbacks {
        public void onBackPressedCallback();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        Log.d("DetailActivity", "user pressed the back button");
        if(mCallbacks != null)
            mCallbacks.onBackPressedCallback();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_note_detail);
        fragment = new DetailFragment();

        getSupportFragmentManager().beginTransaction()
                .add(R.id.detail_container, fragment).commit();

        // Fragment must implement the callback.
        if (!(fragment instanceof Callbacks)) {
            throw new IllegalStateException(
                    "Fragment must implement the callbacks.");
        }

        mCallbacks = (Callbacks) fragment;
    }
}

And the DetailFragment which implements the interface method:

public class DetailFragment extends Fragment  
implements DetailActivity.Callbacks {

    @Override
    public void onBackPressedCallback() {
        //this method is called by the DetailActivity,
        //when its onBackPressed() method is triggered
        Log.d("DetailFragment", "the back button was pressed!");
    }

    //... snipped
}

(Some code has been left out, onCreate and other methods for example.)

The Activity should now notify the Fragment, when the back button has been pressed. This example can ofcourse also be used to notify the fragment of other events too.

I will be creating a new post on using interfaces.

How to know if the Actionbar Home button is pressed

actionbar-home

Similarly to the method above, you can register events for when the Actionbar home button is pressed, and act upon that event in your fragment class.

You can acheive this in a similar fashion to the code above, by listening for the Home button pressed event in your FragmentActivity class:

@Override
public boolean onOptionsItemSelected(MenuItem item) {  
    switch (item.getItemId()) {
        case android.R.id.home: {
            fragment.homeButtonWasPressed();
            return true;
        }
    }
    return super.onOptionsItemSelected(item);
}

And then calling a method in your fragment class, here named homeButtonWasPressed().

More information on Actionbar home button, and back button navigation can be found on Android developer.

Using onPause() in the fragment for saving data before exiting.

If you are just looking for a simple way to know when to save data in your fragment when the user is navigating away, you can always just use the lifecycle callback method onPause() method in the fragment

@Override
public void onPause() {  
    super.onPause();
    Log.d("DetailFragment", "fragment is pausing. save data");
    saveData();
}

Using LocalBroadcastManager

It would also be possible to use the broadcast system for notification. Look here for an example.

For more details on fragments and callbacks, take a look at the Android developers Fragments guide.

If you have any other suggestions, you are most welcome to share them in the comments!

Edit (1 May 2013): Updated the post with an example using interface communication from the FragmentActivity to the Fragment.

comments powered by Disqus