This article was originally published in DZone's 2014 Guide to Mobile Development
Performance is critical when you are building apps for mobile devices. When using a device that is built for accomplishing tasks quickly and on the go, like a smartphone, performance is an even bigger concern than on desktops. Being users ourselves, we all understand this, but we also understand that users can’t see an app’s network timelines or latency scores. The user’s perception of application performance depends upon aesthetic design, feedback to the user, speed of information, and much more. All they see is the user experience you have crafted for them, so even if your performance metrics are great, your apps can still feel slow if you don’t employ the right techniques in your code. In many ways, perceived performance is more important than actual performance. In this article, we’re going to focus on the user’s perception of performance.
Let’s first examine two major use cases for mobile apps: accessing information on the go, and entertainment. If you are accessing information on the go, there is a good chance you are in a hurry or you’re on a limited-speed connection. You need the app to give you the information you need as fast as possible. In the case of entertainment, you just need the app to provide fluid interaction. In this case, performance is part of the entertainment factor. In both of these cases, the app’s performance is not simply characterized by how fast the app is processing information behind the scenes. Rather, this extends into the app’s design and system architecture.
The most immediate factor of an app’s performance actually has nothing to do with raw processing power. User feedback, or some sort of response to user input, is probably the most critical factor to having an app that seems to perform well. If you touch a button, that button should immediately provide feedback to the user. If you swipe across the screen to drag an object, that object should follow the user’s touch immediately.
Most native components will handle user feedback (ie: button states) for you. However, if you are building a mobile web or hybrid application, it is extremely important that you build in some sort of user feedback to inform your users that their input has been received and you are performing some sort of action. The button press case is extremely basic, but if you have a user interface that doesn’t acknowledge the user input, then there is no way for the user to know that the input has been received. Regardless of whether or not this app is actually slow, the user will perceive the app as being slow or buggy simply because there is nothing to let the user know that their input has been received and that the app is preparing a response.
After you’ve tapped a button, does your app let the user know that something is happening, or does the UI simply lock up until the next piece of data is ready? If it’s possible (and in most cases, it is), you should never lock up the user interface thread while you are requesting data from a remote source. This is a major red flag and users will immediately notice when the entire application locks up and becomes unresponsive.
A better way of handling this would be to request data in a background thread (so it does not lock up the UI) and present the user with some sort of visual cue that an action is being performed. By handling data in a background thread, the app stays responsive and never feels like it’s freezing up. If you’re building a hybrid or mobile web app, don’t worry; the browser’s XMLHttpRequest won’t lock up your webview’s UI, so this is less of an issue.
Rather than just making your user wait until data is available before changing views, you can change the user perception and trick them into feeling that the app is faster by providing some sort of feedback. It could be as simple as a spinner or a progress bar, however, these have also been known to draw the user’s attention to the fact that they are waiting. Alternatively, you could create a loading view animation that slowly removes the previous page’s data or shows pieces of the new data as it is loaded. Overall, you want to have some way of entertaining and distracting the user while they wait. By engaging the user with animation, you are changing the perceived performance and user experience of the application, even if the loading time does not actually change.
Familiar Native Physics and Gestures
Buttons and animations are great for any form factor, but the features that make mobile so convenient and elegant to use have always been the touch controls. There is a common set of interface physics and gestures that all popular mobile platforms share, including momentum scrolling, side swipes, pull-to-refresh, and multi-touch zooming controls.
It’s important for app designers to harness these mobile-specific controls wherever they can, and they need to be snappy. Natively built apps don’t have too many issues with these built-in controls, but web and hybrid apps can have issues recreating this functionality. Luckily, there are tools and CSS controls that can help.
Harness the GPU
In many cases, you’ll use animations in your mobile apps, especially in the loading instances mentioned above, but how do you make sure those animations are fluid and snappy? Obviously, stuttering or choppy animations can be very problematic. They give the user the feeling that the app is slow and buggy. This is one of the major issues that people often complain about with HTML-based applications. In native applications, this is less of an issue unless you are doing something extremely complicated. Generally, native animations are fast and smooth.
In HTML applications there are ways to make the app feel faster and make animations smoother. Avoiding computationally-expensive browser reflow operations is critical for making fluid animations. Browser reflow operations occur when your content’s size changes, or the position of your content changes, causing it to impact the layout of neighboring DOM elements. If you change width, height, or top/bottom/left/right styles of a DOM element, this will trigger browser reflow operations.
If you want to animate your content in HTML, you can use CSS transitions or animations with the transform:translate3d (x,y,z) style. This style forces rendering of your DOM content on the GPU and can also be used to move or animate your content without triggering those expensive browser reflow operations. This technique can be used to achieve solid 50-60 frames per second animations in mobile web experiences. However, it is also important to make sure that the DOM elements you are animating don’t exceed the GPU maximum texture size. Otherwise, you could end up with an annoying flicker in your animations, which completely ruins the user experience.
Another technique that you can use to make your application feel extremely fast is to preempt user actions before the user performs them. For example, let’s say you capture an image with your app. You start uploading that image before the user has actually said they’d like to upload the image. The user then enters a name and description, and by the time the user hits the upload button the image is already uploaded. Then, when the user does hit upload, they will be amazed at how quickly the upload took place. This is exactly what Instagram does in their app, and it is part of what set Instagram apart from their competition early on. Preemption doesn’t work in every scenario. You don’t want to aggressively load data that may never be necessary, but it can work extremely well in the cases where it does fit.
All Decisions Must Consider UX
In a nutshell, perceived performance is really all about understanding how the user experiences UI performance, not the actual performance metrics. You need to consider how the end user is going to be impacted by every technical and architectural decision that you make. If there is ever a situation where the user needs to wait, then give them feedback to let them know that the app is still working. Request data during an animation sequence, or play animations while the app is doing something else in the background. Preempt data loading if you can. If you can’t, then you might want to consider lazy-loading your data. If you’re building a web app, let the GPU handle the UI in any way possible. Regardless of the interaction, it is critical to develop your apps in a fashion that tailors the experience to the user’s delight.
Want to read more articles like this? Download the free guide today!