1. Introduction
Last Updated:2021-03-11
Why do we need to measure the performance of Views?
Views are a key part of Android applications that directly affect the user experience. For example, your Activity or Fragment contains the UI which holds the View components that users interact with. Users are not able to see the entire content of the UI until it's completely drawn on the screen. Slow and frozen screens will directly impair user interaction with your app and create a bad user experience.
Doesn't Firebase Performance Monitoring provide these performance metrics out-of-the-box?
Firebase Performance Monitoring automatically captures some performance data out-of-the-box, such as your app start time (i.e., the load time for your first Activity only) and screen rendering performance (i.e., slow and frozen frames for Activities but not for Fragments). However, industry apps usually don't have lots of Activities but rather one Activity and multiple Fragments. Also, many apps usually implement their own Custom Views for more complex use cases. So it's often useful to understand how to measure the load time and screen rendering performance of both Activities and Fragments by instrumenting custom code traces in your app. You can easily extend this codelab to measure performance of Custom View components.
What you'll learn
- How to add Firebase Performance Monitoring to an Android app
- Understanding the loading of an Activity or a Fragment
- How to instrument custom code traces to measure the load time of an Activity or Fragment
- Understanding Screen Rendering and what is a Slow/Frozen frame
- How to instrument custom code traces with metrics to record Slow/Frozen screens
- How to view the collected metrics in the Firebase console
What you'll need
- Android Studio 4.0 or higher
- An Android device/emulator
- Java version 8 or higher
2. Getting set up
Get the code
Run the following commands to clone the sample code for this codelab. This will create a folder called codelab-measure-android-view-performance
on your machine:
$
git
clone
https://github.com/FirebaseExtended/codelab-measure-android-view-performance.git
$
cd
codelab-measure-android-view-performance
If you don't have git on your machine, you can also download the code directly from GitHub.
Import the measure-view-performance-start
project into Android Studio. You will probably see some compilation errors or maybe a warning about a missing google-services.json
file. We'll correct this in the next section of this step.
In this codelab, we'll use the Firebase Assistant plugin to register our Android app with a Firebase project and add the necessary Firebase config files, plugins, and dependencies to our Android project — all from within Android Studio !
Connect your app to Firebase
- Go to Android Studio/ Help> Check for updatesto make sure that you're using the latest versions of Android Studio and the Firebase Assistant.
- Select Tools> Firebaseto open the Assistant
pane.

- Choose Performance Monitoringto add to your app, then click Get started with Performance Monitoring.
- Click the button to create a new project, and then enter a project name (for example,
Measure Performance Codelab). - Click Continue.
- If prompted, review and accept the Firebase terms , and then click Continue.
- (Optional) Enable AI assistance in the Firebase console (called "Gemini in Firebase").
- For this codelab, you do not need Google Analytics, so toggle off the Google Analytics option.
- You should next see a dialog to Connectyour new Firebase App to your Android Studio project.

- Back in Android Studio, in the Assistant
pane, you should see the confirmation that your app is connected to Firebase.

Add Performance Monitoring to your app
In the Assistant pane in Android Studio, click Add Performance Monitoring to your app.
You should see a dialog to Accept Changesafter which Android Studio should sync your app to ensure that all necessary dependencies have been added.

Finally, you should see the success message in the Assistant pane in Android Studio that all dependencies are set up correctly.

As an additional step, enable debug loggingby following the instructions in the step "(Optional) Enable debug logging". The same instructions are also available in the public documentation .
3. Run the app
If you have successfully integrated your app with the Performance Monitoring SDK, the project should now compile. In Android Studio, click Run> Run ‘app'to build and run the app on your connected Android device/emulator.
The app has two buttons that take you to a corresponding Activity and Fragment, like this:

In the following steps of this codelab, you'll learn how to measure the load time and screen rendering performance of your Activity or Fragment.
4. Understanding the loading of an Activity or Fragment
In this step, we will learn what the system is doing during the loading of an Activity or Fragment.
Understanding the loading of an Activity
For an Activity, the load time is defined as the time starting from when the Activity object is created all the way until the First Frameis completely drawn on the screen ( this is when your user will see the complete UI for the Activity for the first time
). To measure if your app is fully drawn, you can use the reportFullyDrawn()
method to measure the elapsed time between application launch and complete display of all resources and view hierarchies.
On a high level, when your app calls startActivity(Intent)
, the system automatically performs the following processes. Each process takes time to complete, which adds to the duration of time between the Activity creation and when the user sees the UI for the Activity on their screen.

Understanding the loading of a Fragment
Similar to the Activity the load time for a Fragment is defined as the time starting from when the Fragment gets attached to its host Activity all the way until the First Framefor the Fragment View is completely drawn on the screen.
5. Measure the load time of an Activity
Delays in the first frame can lead to a bad user experience, so it's important to understand how much initial load delay your users are experiencing. You can instrument a custom code trace to measure this load time:
- Start the custom code trace (named
TestActivity-LoadTime) in the Activity class as soon as the Activity object is created.
TestActivity.java
public
class
TestActivity
extends
AppCompatActivity
{
//
TODO
(
1
):
Start
trace
recording
as
soon
as
the
Activity
object
is
created
.
private
final
Trace
viewLoadTrace
=
FirebasePerformance
.
startTrace
(
"TestActivity-LoadTime"
);
//
...
}
- Override the
onCreate()callback, and get the View added by thesetContentView()method.
@Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
//
Current
Activity
's main View (as defined in the layout xml file) is inflated after this
setContentView(R.layout.activity_test);
// ...
// TODO (2): Get the View added by Activity'
s
setContentView
()
method
.
View
mainView
=
findViewById
(
android
.
R
.
id
.
content
);
//
...
}
- We've included an implementation of
FistDrawListener, which has two callbacks:onDrawingStart()andonDrawingFinish()(see the next section below for more details aboutFirstDrawListenerand what can affect its performance) . Register theFirstDrawListenerat the end of Activity'sonCreate()callback. You should stop yourviewLoadTracein theonDrawingFinish()callback.
TestActivity.java
// TODO (3): Register the callback to listen for first frame rendering (see
// "OnFirstDrawCallback" in FirstDrawListener) and stop the trace when View drawing is
// finished.
FirstDrawListener
.
registerFirstDrawListener
(
mainView
,
new
FirstDrawListener
.
OnFirstDrawCallback
()
{
@
Override
public
void
onDrawingStart
()
{
// In practice you can also record this event separately
}
@
Override
public
void
onDrawingFinish
()
{
// This is when the Activity UI is completely drawn on the screen
viewLoadTrace
.
stop
();
}
});
- Re-run the app. Then, filter the logcat with " Logging trace metric". Tap on the
LOAD ACTIVITYbutton, and look for logs like below:
I/FirebasePerformance: Logging trace metric: TestActivity-LoadTime (duration: XXXms)
🎉 Congrats! You've successfully measured the loading time of an Activity and reported that data to Firebase Performance Monitoring. We'll view the recorded metric in the Firebase console later in this codelab.
Purpose of FirstDrawListener
In the section just above, we registered a FirstDrawListener
. The purpose of FirstDrawListener
is to measure when the first frame has begun and finished drawing.
It implements the ViewTreeObserver.OnDrawListener
and overrides the onDraw()
callback which is invoked when the View tree is about to be drawn. It then wraps the result to provide two utility callbacks onDrawingStart()
and onDrawingFinish()
.
The complete code for FirstDrawListener
can be found in this codelab's source code
.
6. Measure the load time of a Fragment
Measuring the load time of a Fragment is similar to how we measure it for an Activity but with some minor differences. Again, we'll instrument a custom code trace :
- Override the
onAttach()callback and start recording yourfragmentLoadTrace. We'll name this traceTest-Fragment-LoadTime.
As explained in an earlier step, the Fragment object can be created anytime, but it becomes active only when it's attached to its host Activity.
TestFragment.java
public
class
TestFragment
extends
Fragment
{
//
TODO
(
1
):
Declare
the
Trace
variable
.
private
Trace
fragmentLoadTrace
;
@
Override
public
void
onAttach
(
@
NonNull
Context
context
)
{
super
.
onAttach
(
context
);
//
TODO
(
2
):
Start
trace
recording
as
soon
as
the
Fragment
is
attached
to
its
host
Activity
.
fragmentLoadTrace
=
FirebasePerformance
.
startTrace
(
"TestFragment-LoadTime"
);
}
- Register the
FirstDrawListenerin theonViewCreated()callback. Then, similar to the Activity example, stop the trace in theonDrawingFinish().
TestFragment.java
@Override
public
void
onViewCreated
(
@NonNull
View
mainView
,
Bundle
savedInstanceState
)
{
super
.
onViewCreated
(
mainView
,
savedInstanceState
);
//
...
//
TODO
(
3
)
:
Register
the
callback
to
listen
for
first
frame
rendering
(
see
//
"OnFirstDrawCallback"
in
FirstDrawListener
)
and
stop
the
trace
when
view
drawing
is
//
finished
.
FirstDrawListener
.
registerFirstDrawListener
(
mainView
,
new
FirstDrawListener
.
OnFirstDrawCallback
()
{
@Override
public
void
onDrawingStart
()
{
//
In
practice
you
can
also
record
this
event
separately
}
@Override
public
void
onDrawingFinish
()
{
//
This
is
when
the
Fragment
UI
is
completely
drawn
on
the
screen
fragmentLoadTrace
.
stop
();
}
}
);
- Re-run the app. Then, filter the logcat with " Logging trace metric". Tap on the
LOAD FRAGMENTbutton, and look for logs like below:
I/FirebasePerformance: Logging trace metric: TestFragment-LoadTime (duration: XXXms)
🎉 Congrats! You've successfully measured the loading time of a Fragment and reported that data to Firebase Performance Monitoring. We'll view the recorded metric in the Firebase console later in this codelab.
7. Understanding Screen Rendering and what is a Slow/Frozen frame
UI Rendering is the act of generating a frame from your app and displaying it on the screen. To ensure that a user's interaction with your app is smooth, your app should render frames in under 16ms to achieve 60 frames per second ( why 60fps? ). If your app suffers from slow UI rendering, then the system is forced to skip frames, and the user will perceive stuttering in your app. We call this jank.
Similarly, frozen frames are UI frames that take longer than 700ms to render. This delay is a problem because your app appears to be stuck and is unresponsive to user input for almost a full second while the frame is rendering.
8. Measure the Slow/Frozen frames of a Fragment
Firebase Performance Monitoring automatically captures slow/frozen frames for an Activity ( but only if it is Hardware Accelerated
). However, this feature is currently not available for Fragments. The slow/frozen frames of a Fragment is defined as the slow/frozen frames for the entire Activity between the onFragmentAttached()
and onFragmentDetached()
callbacks in the Fragment's lifecycle.
Taking motivation from the AppStateMonitor
class ( which is a part of the Performance Monitoring SDK responsible for recording screen traces for Activity
), we implemented the ScreenTrace
class ( which is part of this codelab source code repo
). ScreenTrace
class can be hooked up to the Activity's FragmentManager
's lifecycle callback to capture slow/frozen frames. This class provides two public APIs:
-
recordScreenTrace(): Starts recording a screen trace -
sendScreenTrace(): Stops the recording of a screen trace and attaches custom metrics to log Total, Slow, and Frozen frame counts
By attaching these custom metrics, screen traces for Fragments can be handled the same way as screen traces for an Activity and can be displayed along with other screen rendering traces in the Performance dashboard of the Firebase console.
Here's how to log screen traces for your Fragment:
- Initialize the
ScreenTraceclass in your Activity that hosts the Fragment.
MainActivity.java
//
Declare
the
Fragment
tag
private
static
final
String
FRAGMENT_TAG
=
TestFragment
.
class
.
getSimpleName
();
//
TODO
(
1
):
Declare
the
ScreenTrace
variable
.
private
ScreenTrace
screenTrace
;
@
Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
activity_main
);
//
TODO
(
2
):
Initialize
the
ScreenTrace
variable
.
screenTrace
=
new
ScreenTrace
(
this
,
FRAGMENT_TAG
);
//
...
}
- When you load your Fragment, register for
FragmentLifecycleCallbacksand override theonFragmentAttached()andonFragmentDetached()callbacks. We have done this for you. You need to start recording screen traces in theonFragmentAttached()callback and stop recording in theonFragmentDetached()callback.
MainActivity.java
private
final
FragmentManager
.
FragmentLifecycleCallbacks
fragmentLifecycleCallbacks
=
new
FragmentManager
.
FragmentLifecycleCallbacks
()
{
@Override
public
void
onFragmentAttached
(
@NonNull
FragmentManager
fm
,
@NonNull
Fragment
f
,
@NonNull
Context
context
)
{
super
.
onFragmentAttached
(
fm
,
f
,
context
);
//
TODO
(
3
)
:
Start
recording
the
screen
traces
as
soon
as
the
Fragment
is
//
attached
to
its
host
Activity
.
if
(
FRAGMENT_TAG
.
equals
(
f
.
getTag
())
&&
screenTrace
.
isScreenTraceSupported
())
{
screenTrace
.
recordScreenTrace
();
}
}
@Override
public
void
onFragmentDetached
(
@NonNull
FragmentManager
fm
,
@NonNull
Fragment
f
)
{
super
.
onFragmentDetached
(
fm
,
f
);
//
TODO
(
4
)
:
Stop
recording
the
screen
traces
as
soon
as
the
Fragment
is
//
detached
from
its
host
Activity
.
if
(
FRAGMENT_TAG
.
equals
(
f
.
getTag
())
&&
screenTrace
.
isScreenTraceSupported
())
{
screenTrace
.
sendScreenTrace
();
}
//
Unregister
Fragment
lifecycle
callbacks
after
the
Fragment
is
detached
fm
.
unregisterFragmentLifecycleCallbacks
(
fragmentLifecycleCallbacks
);
}
}
;
- Re-run the app. Then, tap on the
LOAD FRAGMENTbutton. Wait for a few seconds, then click theback buttonon the bottom navigation bar.
Filter the logcat with " Logging trace metric", then look for logs like below:
I/FirebasePerformance: Logging trace metric: _st_MainActivity-TestFragment (duration: XXXms)
Filter the logcat with " FireperfViews", then look for logs like below:
D/FireperfViews: sendScreenTrace MainActivity-TestFragment, name: _st_MainActivity-TestFragment, total_frames: XX, slow_frames: XX, frozen_frames: XX
🎉 Congrats! You've successfully measured the Slow/Frozen frames for a Fragment and reported that data to Firebase Performance Monitoring. We'll view the recorded metrics in the Firebase console later in this codelab.
9. Check metrics in the Firebase console
- In the logcat, click the Firebase console URL to visit the details page for a trace.

Alternatively, in the Firebase console , select the project that has your app. In the left panel, locate the Release & Monitor section, then click Performance.
- In the main Dashboardtab, scroll down to the traces table, then click the Custom tracestab. In this table, you'll see the custom code traces we added earlier plus some out-of-the-box traces
, such as
_app_starttrace. - Find your two custom code traces,
TestActivity-LoadTimeandTestFragment-LoadTime. Click on the Durationfor either one to view more details about the collected data.

- The detail page for the custom code trace shows you information about the duration of the trace (i.e., the measured load time).

- You can also view the performance data for your custom screen trace.
- Go back to the main Dashboard
tab, scroll down to the traces table, then click the Screen rendering
tab. In this table, you'll see the custom screen traces we added earlier plus any out-of-the-box screen traces
, such as
MainActivitytrace. - Find your custom screen trace,
MainActivity-TestFragment. Click the trace name to view the aggregated data of slow rendering and frozen frames.

10. Congratulations
Congratulations! You've successfully measured load time and screen rendering performance of an Activity and a Fragment by using Firebase Performance Monitoring!
What you have accomplished
- You integrated Firebase Performance Monitoring into a sample app
- You now understand the life cycle of View loading
- You measured load time of both an Activity and a Fragment by adding custom code traces
- You recorded slow/frozen frames by adding custom screen traces with custom metrics
What's next
Firebase Performance provides more ways of performance measurement of your app other than custom trace. It automatically measures app startup time, app-in-foreground, and app-in-background performance data . It's time for you to check these metrics in the Firebase Console .
Also, Firebase Performance offers automatic HTTP/S network request monitoring . With that you can easily instrument network requests without writing a single line of code. Can you try sending some network requests from your app and find the metrics in the Firebase console ?
Bonus
Now that you know how to measure the load time and screen rendering performance of your Activity/Fragment by using custom code traces, can you explore our open sourced code base to see if you can capture those metrics out of the box for any Activity/Fragment that is a part of the app? Feel free to send the PR if you wish :-)
11. Bonus Learning
Understanding what's happening during the loading of an Activity will help you better understand the performance characteristics of your app. In an earlier step, we described at a high level what happens during the loading of an Activity, but the following diagram describes each phase in much higher detail.


