In my previous post, I detailed the steps I took to improve performance on an existing Titanium app. In this post, I summarize the things I try to do from a performance perspective to make the development process easier, give the client the best value and deliver the best possible experience for the user:
Stick to a single codebase — In my experience, there’s no reason to have multiple codebases per application — it creates more work and introduces more issues. With some simple scripting, it’s possible to have one codebase building multiple apps and sharing 90%+ code. I use Alloy to partition code using conditions like
OS_IOSand use platform folders only when necessary — this way only the relevant code / files are included in the build which keeps file sizes down compared to classic Titanium. I’ll use Alloy
requirein XML files where I need to re-use views across different XML files that might be platform-specific.
Redefine Alloy tags — In Alloy, it’s possible to write your own tags or redefine existing ones — there’s a blog post on how to do this. It’s an incredibly useful feature as it means you can reduce the need to use
requireor split XML files per platform. For example, you can create a NavigationWindow tag that will return a
Ti.UI.iOS.NavigationWindowin iOS or its default / primary
Ti.UI.Windowelement in Android. Using this technique, I’ve also created my own PickerField control for projects, which renders a normal slide up Picker for iPhones, a pop-up Picker for Android, and a floating window Picker for Tablets, all by using one XML tag.
Keep controller code to a minimum — if I ever start writing a lot of code in a controller, I’ll look for ways to reduce this by moving functions into a library file. Where possible, I want to keep controller code to a minimum so it’s just handling rendering changes, with business logic being handled elsewhere. This not only makes controllers easier to work with, it allows you to test business logic in one place, before it ever reaches a controller / view.
Structure assets per platform — Having lots of images makes an app bulkier and 90% of the time any button graphic given by a designer can be created in code. So, I tend to use coded buttons and controls rather than graphical ones, unless it’s absolutely necessary for the app. If I do have to use images, I make sure I’ve optimised them to be as small as possible and place them in the correct platform folders, so they’re only included in the appropriate platform build.
Use Native elements – Tab Group and Navigation Window for iOS are provided for free in the Titanium SDK — there may be situations where I have to develop my own, but I try to keep this to minimum. Using native components requires less code and provides a faster user interface. I’ll review designs and convince the client where possible that it’s best to use native OS components to keep the app running smoothly.
Another good reason for sticking to standard UI components is when it comes to supporting OS changes or new devices. For example, with the recent release of the iPhone X, many iOS developers had to spend more time tweaking their apps because their custom, non-UIKit controls didn’t adapt automatically to the new home indicator and “notch”.
Use a List View instead of a Table View — For big lists, I love the performance of a List View especially on Android. There are still good reasons to use Table Views as they can do things List Views can’t, but ideally big lists should use List Views to get the best possible native performance.
Reduce over-the-bridge calls — I’ll create elements with one or minimal calls, especially in loops. If I ever have to add properties later, I’ll use
.applyProperties()to apply multiple properties with one call. Also, I avoid using named colours like
blackand use the raw hex value instead — it’s a tiny overhead but it’s one less lookup that has to happen behind the scenes.
Use widgets, libraries, modules — One of the first things I’ll do when taking on a potential project is to look up what exists out there already in the form of libraries or modules I can reuse. Where I do have to write my own, I’ll try to make them reusable. There’s a lot to be said for standardising certain aspects of an app — for example, creating a push notification or GPS module that can be “dropped” into any app and spun up with a couple of simple method calls.
I like many developers, still experiment with each app I build — trying subtle (and sometimes more radical) ideas to make it easier to develop. I’ll be sharing some experiences of these in the coming weeks and months, but for now I hope these performance posts have been informative. Please leave comments and feedback below – especially any tips and tricks you use to make development easier!