Simple trick to use and manage Toolbar with Fragments in Android

Hi, guys! I have been recently searching about using Toolbar with Fragments, because I needed to set and then modify toolbar in Fragment after splash screen ends and new fragment appears. But the result I got was nothing like:

((ActionBarActivity)getActivity()).setSupportActionBar(mToolbar);

and with new AppCompatActivity:

((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);

using this directly in the Fragment code. But it didn’t help me. So I’ve found better solution that might help you to realize this feature. But before we go you need to know that this method uses only one toolbar along whole lifecycle of application. But no one prevents us to modify toolbar on each screen ;)

The idea is very simple like a piece of cake. We’ll use additional fragment with setRetainInstance(true) called in onCreate method of fragment. The real purpose of this method is to change fragment’s behavior avoiding it to be recreated that means it saves all variables we initialized in the class which extends Fragment at any configuration changes. So why don’t we create toolbar once and pass it into retained fragment and then use it again at any part of code? That sounds great. All we need to do is just create seperate public class, let’s call it RetainFragment:

public class RetainFragment extends Fragment {
private Object mObject;
/**
* Empty constructor as per the Fragment documentation
*/
public RetainFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Make sure this Fragment is retained over a configuration change
setRetainInstance(true);
}
/**
* Store a single object in this Fragment.
*
* @param object The object to store
*/
public void setObject(Object object) {
mObject = object;
}
/**
* Get the stored object.
*
* @return The stored object
*/
public Object getObject() {
return mObject;
}
}

After we can write somewhere in our project public static function that returns us already created instance of RetainFragment or in other case creates it if it has not done yet. This is our public static method:

public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
// Check to see if we have retained the worker fragment.
RetainFragment mRetainFragment = (RetainFragment)fm.findFragmentByTag("Retain");
// If not retained (or first time running), we need to create and add it.
if (mRetainFragment == null) {
mRetainFragment = new RetainFragment();
fm.beginTransaction().add(mRetainFragment, "Retain").commitAllowingStateLoss();
}
return mRetainFragment;
}

The most part of code is done. Now we only have to call method findOrCreateRetainFragment(FragmentManager fm) anywhere we need this fragment. But we completely forgot about toolbar. How to pass it into RetainFragment? Simply, just in onCreate method of your MainActivity call findOrCreateRetainFragment, and then using setObject() method of the instance send your toolbar as the argument. That’s all. Whenever you need your toolbar you again call first findOrCreateRetainFragment() and then getObject() using explicit casting. That’s example code, where CommonData is some public class with defined static method findOrCreateRetainFragment into it:

Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
RetainFragment rf = CommonData.findOrCreateRetainFragment(getSupportFragmentManager());
rf.setObject(getSupportActionBar());

Using toolbar somewhere in different class:

RetainFragment rf = CommonData.findOrCreateRetainFragment(getFragmentManager());
((ActionBar)rf.getObject()).setLogo(R.drawable.myapp_ico);

That’s all.Hope you found this article useful for you. Note, that you can use this “trick” not only with toolbar, of course. Just use it anytime you need to save some instance, and even array of completely different objects. Of course, it’s not professional to use this technique at all places of your code instead of creating appropriate constructors of classes to pass objects as arguments. So, think twice before using it. If you have any ideas about this problem, write comments — it will be interesting to read other solutions. And, of course, ask questions if you have any.