The problem

When designing an application, I had a problem with my fragments’ interaction. I decided to let my activity hold every information important to my Application, and let the fragments access those data directly via the Activity. The problem is that Fragments and Activities aren’t supposed to be that tightly coupled. A fragment is supposed to be independent from its activity lifecycle, and we’re going to see why…

Be careful with your Bundles.

Ok, just imagine that you have your Activity, that holds some API result information. This API information needs to be provided to all of your fragments inside your activity. No problem, you can create your fragment using a static method, pass the information you need via a Bundle, and use a callback to update the data as needed. It would seem rather easy, and is what Android Studio propose to generate when you create a new Fragment.

public static MyFragment newInstance(Shop shop) {
	MyFragment c = new MyFragment();
	Bundle b = new Bundle();
	b.putParcelable(MyFragment.SHOP_KEY, shop);
	c.setArguments(b);
	return c;
}

Note
A Parcelable object allows you to write and restore your data from a “Parcel”. This lets you serialize your data, so that it can be restored later.

It looks like a good solution, except you need to be careful. A question that popped to my mind was whether or not using a bundle to pass some data between fragments and activities would return the same instance of your class. To test this, I decided to play with the Logcat and display the object.toString(), before and after passing it via a Bundle. As far as my tests went, the objects are of the same instance. So if you modify the object in your fragment, you won’t need to modify it in your Activity. If you’re simply changing a name it’s not really important, but if you’re adding an item to a list, you might want to note that.

You might also know that, depending on your activity’s/fragment’s state, your app might be killed. There’s a magical little method called onSaveInstanceState(Bundle), that allows you to save some data before getting killed in both your fragments and your activity, so that you can retrieve them later. It is for example called when you change your phone’s orientation, letting you save your state and retrieve it once the orientation is changed. So, now, imagine you’d want to save your data (let’s stay with a Shop example), into your savedInstanceState Bundle, you’d simply do the following:

@Override
public void onSaveInstanceState(Bundle outState) {
	super.onSaveInstanceState(outState);
	outState.putParcelable(MyFragment.SHOP_KEY, mShop);
}

And you’d be able to retrieve it in your onCreate as follow

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	if(savedInstanceState != null) {
		mShop = (Shop) savedInstanceState.get(MyFragment.SHOP_KEY);
	}
}

Now, let’s assume that since you want your Shop to be saved in both your fragment and in your activity, you save your shop in both your activity’s onSaveInstanceState, and your Fragment’s. Do you think that after your app gets put on background and killed, the Shop contained in your activity and in your fragment will still be of the same instance? Well, no! Not only it isn’t the same instance as before (which seems logic, since your Fragment and Activity got destroyed), but the two Shops aren’t of the same instance at all! See the following logcat:

The Fragment even receives the Shop twice after the destruction of the app, once from the arguments (that it still holds), and once from the savedInstanceState that it saved earlier. And note that none of those are the same instance as the Shops from the Activity.

Now, let’s go a little further and see what’s going on. My Shop implements the Parcelable interface, which is supposed to help storing information temporarily in bundles. Let’s see when the system calls this interface. I simply added a few Log inside of the writeToParcel(), and the constructor which uses the Parcel to construct the object. And here is the Logcat:

So, as you can see, the calls to the writeToParcel() are only made when we are using onSaveInstanceState(Bundle). This means that depending on when you use a Bundle, the putParcelable() method don’t seem to behave the same way. Moreover, we can see that this is done 3 times: Two of them are from the Activity and Fragment onSaveInstanceState, and the last one must be from the Fragment’s getArgument’s one. This would explain why the Fragment is able to access getArguments(), even after it has been destroyed: the system must save the arguments Bundle, and restore it to give it to us later.

So it’s a bit enigmatic to me right now, when the writeToParcel() method is called. The Bundle implementation seems rather simple as it stores the Parcelable object into an HashMap. I suppose that it is called during the fragment Lifecycle, where the Bundle issued from onSaveInstanceState() would be store in a more persistant storage, using the Parcelable interface on the object from the Bundle.

So, ok we need to be careful while passing some data through a Bundle. We could say that instead of doing that, we’d simply use a Callback from a Fragment to the Activity, getting the Activity’s reference of our Shop, and always working with it in our Fragment. Once again, we need to be careful. If we look deeper to our logcat’s above, we can see that the fragment’s onCreate is called before the activity’s. This is confirmed by the documentation, that states that we need to wait for our Fragment’s onActivityCreated() callback for the activity to be created. So we would be able to get our data from our Activity only once the view is created, and populate it with our data by then. It might make our code look quite messy…

You can find the source code used to generate the Logcat on this gist.

The solution

The fact is that we need to loosen the links between our Activity and our Fragment. We need to be able to make a Fragment work, even if our Activity isn’t created, and still let our Activity know about our data updates. To do so, we need to focus on two thing: where to get the data, and how to send the updates of our model.

The first solution is pretty simple. We could just put our data into a SQLite Database, and retrieving it asynchronously in our Fragment. This is quite easy to achieve, and well documented.

For the other one, a design pattern called a BusEvent might interest us. To make it as easy as possible to understand, the BusEvent pattern let’s us define some event, that can be thrown toward a Bus, and will be delivered to every subscriber. This way, our Activity will be notified about any event it subscribed to, thrown by our Fragment.

This would allow us to, for example, to change the Shop’s name in our Fragment, change the information stored in the database, and once it’s done, simply send an event through our bus saying “Hey, to anyone interested, the shop has been updated”. Then, on our Activity, we’d simply subscribe to those kind of event on our Bus, and we would be able to know when the Shop has been modified. Then, we’d simply need to retrieve it from the database, and work with it.

Let’s briefly see how to use an event bus library on Android. The one I recently used is called Otto, and was made by the awesome people from Square.

Otto

Otto is a BusEvent implementation, based on Guava. It’s really simple to use, and well documented on square’s website. I’ll simply show you how to easily implement what I’ve been talking about up here.

First, we need to be able to have the same Bus instance, over our application. To do so, you can simply create a singleton bus:

public class BusProvider {
	private static final Bus BUS = new Bus();
	private BusProvider() {}
	
	public static Bus getInstance() {
		return BUS;
	}
}

Then, we can declare an event type. This will be the event thrown through our Bus, to notify of a shop name that changes.

public class ShopEvent {
	private final String mNewName;
	
	public ShopEvent(String newName) {
		this.mNewName = newName;
	}

	public String getmName() {
		return mNewName;
	}
}

We now need to make our Activity register to our Bus : just call BusProvider.getInstance().register(this), in your Activity’s onResume(), and BusProvider.getInstance().unregister(this), in onPause().

Then we define a method, with the @Subscribe annotation, and a single argument corresponding to our Event type.

@Subscribe onShopChangingName(ShopEvent shopEvent) {
	//do stuff
}

Now, everytime someone will send a “ShopEvent” event to the bus, our Activity will be notified. So, to send this ShopEvent, we simply need to use the post(Object event) of our Bus, with as argument, an instance of our ShopEvent.

BusProvider.getInstance().post(new ShopEvent("Caramba!"));

Once posted, every class that subscribed to the ShopEvent event type, via our Bus, will be notified of this new events!

Pro-tip:
There is an Intellij plugin for Otto. It allows you to go back and forth in the events posted by Otto. See here for more information!

I’ll leave you find a lot more example on how to use Otto, including otto samples, and its documentation. I hope this article helped you think about how to do in-app communication in Android. If you have any suggestion, question, or you think I forgot something, feel free to comment below! :-)

A few days ago, I struggled with a simple use case: in an Android Application, I wanted to show a simple tutorial item (displayed as a Card View), but only until the user acknowledged he knew how the app works.

To do so, I first decided to put this simple view in my layout with a visibility of GONE, and changing its visibility based on a SharedPreference item telling if the user knew how the app worked. This solution was simple enough, but I was wondering, wouldn’t it be bad for performance if we need to inflate a view that will never be shown?

So, the other solution I thought about was to inflate this view only when the user open the app for the first few time. This would require to do the inflation programmatically, which requires to call inflater.inflate twice, and might be even worse in term of performances.

I decided to ask it on StackOverflow, searching if some people might have looked into this before. As I waited for an answer, someone commented asking “What did you try?”, and I realized that this guy was totally right! I could try to use DDMS to benchmark the two different solutions, and see what would happen. So, this is what I did.

Brief presentation of DDMS

DDMS is the Dalvik Debug Monitor Server. It provides debugging tools that you often use (Logcat, thread and heap information…). The binary for DDMS is located in the tools directory of the SDK and can be launched using the ddms binary. it consists of a simple window showing you the different debugging tools.

The tool we will be interested in today is called Traceview. It allows you to generate some execution log using the android.os.Debug class, and seeing them graphically.

TIP
Add the sdk/tools and sdk/platform-tools to your PATH environment variable. See this post if you need help.

Generating your execution log

Generating your execution log is really simple, all you need to do is use

Debug.startMethodTracing("your_filename");

which will generate a file in /sdcard/your_filename.trace. And don’t forget to stop the method tracing:

Debug.stopMethodTracing();

Reading those log

First, you’ll need to retrieve the tracelogs files from your phone to your computer. You’ll just need to execute a adb pull /sdcard/your_filename.trace ..

Once you have the log files, just launch the monitor binary, located in the tools folder of your sdk. You’ll then be able to open a file (file > open file). Then, that’s it. You’ll have your trace log opened on your computer, ready for you to analyse it.

Back to the issue: visibility changes vs java inflation.

I’ve created a simple Gist showing the project I used to generate the logs I will try to focus on in this post. It simply start the logs in the fragment onAttach(), and stops them in the fragments onResume() You can find the log I generated with this post here.

So, let’s think about our problem. First what do we want to focus on? Since the view is most of the time hidden, we want to focus on the time performances when inflating the layout, without showing the tutorial view. But, since we don’t want to discourage the user on first uses, we still want a fast inflation speed when we display the view.

What we’ll ask here is, would it be a good idea to switch from the first solution (inflating a layout with some GONE views), to the other one (inflating only what’s important, and adding the tutorial view when we need to).

Displaying the view

So, let’s first compare the performances when we display the tutorial item.

The first image represent the log file for when we simply change the view’s visibility from GONE to VISIBLE. The second represent the log file when we inflate the view programmatically in the fragment’s onCreateView. As we can see, the two log files look a little bit the same, with a smaller exec time (max msec), in favor of the first one (75msec vs 110 msec). From the Profile Panel, we can see the spare call to LayoutInflater.inflate() when inflating the view programmatically, which takes up some precious time (highlighted in red on the screenshots).

So, switching from the first method to the second would decrease our inflation speed of about 31%.

Hiding the view

From the logs, this is what we can see:

From left to right: the representation of the log file when we inflate the layout containing the GONE view, and the representation when inflating the view without the tutorial view. So, as expected, inflating a more complex layout, even when some views’ visibility are set to GONE, takes more time than inflating the simpler view, without the hidden views. What I didn’t expect was the ratio of almost 1:3 for the execution time (102msec vs 39msec). Yeap, the inflated view was a bit complex, but still, I didn’t think letting it to GONE would be that bad for performances when inflating the layout.

So, switching from the first method to the second one would increase our inflation speed of about 161%. Yay!

Note
We need to note that here, the layouts used are really simple. This explains why the speed increase are that important.

Conclusion

So, to conclude about this, inflating a layout with some views with a visibility set to GONE is bad for performances, especially if the view is a bit complex. If you don’t want to show this view verry often, I would suggest you to create a separate xml file containing your view, inflating this layout when needed, and adding it to your main layout programmatically.

I hope you learned some stuff, and if you feel that you can add some information in here or that you don’t understand something, feel free to comment this post or to email me !

Edit
As said in comments, a simpler way to manager this kind of view would be to use ViewStub. It allows you to inflate easily a view when needed, without doing it programmatically. This article is here to explain how to easily use TraceView to test your app’s performance, and let people know that inflating views which will stay as GONE forever is bad!

So, this is my first blog post.

First let me introduce myself. My name is Mickael, I’m a student in an Engineering school in Toulouse, France (INSA). I’ve been found of computer science since I was young enough to hold a mouse in my hand, and now, I consider myself as a self-taught android developper. I’m always trying to expand my knowledge, especially in CS, and that’s why I’m opening this blog now.

What to expect?

Around here, I’ll be talking a lot about Android Development. Since I’ve been working on Android for a few years, I’ve started to find some interesting stuff that I could share with you. I’ll also try to share with you the different project I’m working on, and those I worked on a few years ago.

Feel free to follow me on twitter, comment the posts, and share the articles if you like them! :-)

Cheers!