Transitioning from Titanium to Flutter: a technical summary
Axway, the company that supports and develops the cross-platform mobile development platform Titanium, has recently announced that it will no longer support the software past March 1, 2022 and will close down Axway Cloud Services from September 1, 2022. This article considers other options for future development for individuals and companies that currently use Titanium, who may be looking for alternatives, with a focus on my personal experiences transitioning from Titanium to Flutter. For Axway Cloud Services there is no question that an alternative has to be found. I never rated this service and never recommended it for any clients, but I have had to use it on inherited projects where it was painful to do so because of numerous bugs (and that was just notifications). There are obviously many alternatives for backend services, but I won’t cover that in this article.
As Flutter is backed by Google it is first and foremost a Material Design framework. This means it is naturally, out-of-the-box, predisposed for Android development. Material design can, of course, be used on iOS, but it is not the native Apple look and feel. The drawback, on iOS, is that the UI is drawn by Flutter. A whole set of SDK calls — prefixed by “Cupertino” — exist to emulate the look and feel of iOS. But they are written by the Flutter engineers and are not an exact copy, although they are very close (you can probably talk to any graphic designer to back me up on this). Also, not all the native iOS UX is covered, although probably will be eventually. Now, I am a designer and UX specialist, as well as being a developer, and so this does hurt my aesthetic sensibilities, but at the end of the day I am not sure the end client is bothered much by this. As well as this, iOS and Android consistently seem to copy from each other. An example is that the “…” Menu was never standard on iOS, but was and is in Android Material Design. This is now supported and used in quite a few apps on iOS. So if you can live with this disadvantage, then Flutter will be a perfect solution. Otherwise, one should consider React Native. My main overriding persuasive point going for Flutter is the extended platform support for web and desktop. The web support has only just reached a stable version and does, from my experience, suffer from a lot of problems still. It doesn’t compete at all with sites built with any modern framework — such as React, Angular or Vue — yet, but could in the future.
Now a list of assorted differences I have found between using Titanium and Flutter/Dart.
Ease of Coding
Flutter is slightly harder to use than Titanium. It takes a while to get your head around the state model they use rather than the imperative programming style used in Titanium — React Native is somewhere in-between the two. Flutter works by composition of widgets, where everything is a widget (even UI event listeners). But once you get it and learn the paradigms, on the whole you can do things quicker and more efficiently than in Titanium or React Native as there is so much ready-made boiler plate. For example, loading dynamic data in a list or table view can be done with just one base widget (such as a FutureBuilder or variations of the basic scrolling views). No need to add listeners and get involved with Alloy’s Backbone syncing as one does in Titanium.
Style and MVC Differences
In Flutter everything is controller code, so no separation of views and styling as in Alloy XML/TSS. I must admit I miss this as I do love Alloy (there is regular discussion online about this in Flutter and so it is perfectly possible this may come in the future). Base flutter doesn’t have an underlying MVC framework, although you can create your own. Regular flutter code can be a bit verbose sometimes with nesting widget nightmares, but editing in Visual Studio is a delight with fantastic auto-formatting and completion etc (Android Studio offers good support for Flutter too, but I haven’t used it).
“Hot reload” works really well in Flutter and is super fast. In the early days using Titanium I, and most people, used TiShadow for hot reloading, but it was very temperamental. Lately Titanium LiveView works well. Flutter’s setup can be temperamental too, but when it is setup and working it is really fast.
Flutter is easy to setup and install. There is an issue with version support, as by default one can’t easily switch between versions of the SDK or use different versions for different projects. However, fvm (Flutter Version Manager ) does support this and I have found it to be invaluable. I have had a nightmare updating older downloaded example projects because of iOS native incompatibilities, which is a known problem with Flutter. Flutter works really well with Visual Studio. Titanium tooling/building breaks almost always upon SDK or Xcode version upgrades, but Titanium also works well with Visual Studio and so there isn’t much difference overall on balance. There are some super new tools that have just been announced with Flutter 2.0, but I’ll leave you to research that.
There are fantastic learning resources for flutter. The official documentation is comprehensive and solid. There are tons of Udemy courses, posts and general online discussion. Titanium over the years has had very sporadic and random support. The official documentation has always been under par, with not a lot of real world examples (apart from a few great books which are, as with all software, now out of date). There is a Flutter Slack group, but overwhelming in the number of people and channels on there and so I haven’t used it so much. Nothing to match the fantastic, but small, niche group that we Titanium users are that can be found at TiSlack.
Flutter mobile is not fully complete yet, especially for iOS (at least it is in general coverage, but some of the individual bits or widget properties aren’t fully comprehensive yet). An example I came across is video playback support, where not all native functionality is supported yet. Some people have mentioned Maps as a problem. The Google Maps plugin (Flutter calls its modules packages or plugins) is in version 2.0 now and has been around for more than 2 years. I haven’t used maps yet so can’t say exactly. I am using a 3rd party web view package InAppWebView which is great. If it isn’t fully supported by core Flutter there is likely a 3rd party library to fulfil any requirements. There is a huge community of third party packages and at the latest count — advertised at Flutter Engage — there are more than 15,000. For example, I found a great package (in fact two) to create dynamic PDFs in-app, which I haven’t been able to find for Titanium. Core Flutter development is steady and over time it will reach full native parity (remember Flutter is only 2 years out of version 1, whereas Titanium has been around since before 2010).
I haven’t tried to write a native plugin for Flutter yet, but it seems that it isn’t too difficult — see here for more details. Titanium has a mixed bag of plugins which are often out of date or barely supported and if one doesn’t exist it is sometimes difficult to find someone to write one. Titanium’s hyperloop for me has been so inconsistent and lacking in support and documentation that it never was an advantage. I am not a native developer and so rely on 3rd party modules or hiring native developers to implement specialised functionality.
Firebase integrates really well with Flutter and is very easy to code in an app and generally easy to use as a backend service. Probably as they are both from Google! Titanium, on the other hand, still does not have a full suite of firebase modules (no cloud file storage or firestore for Android) and it is not officially supported by Axway (not that that will matter moving forward).
- Text and TextFields
Flutter’s Text and TextField widgets are more comprehensive than Titanium one’s. They support more styling out-of-the-box, although one can always reproduce this in Titanium by creating Titanium custom Widgets. Forms likewise have a bit more cladding. Flutter Text widgets at their base level are composed of pure Rich Text widgets and so are very configurable and styling text, with accurate font metrics (using advanced features such as ligature control, for example), is really easy and much more powerful than with Titanium.
Navigation is a strange one in Flutter. Titanium navigation has always been really easy with smooth native-performance transitions and support — on iOS especially — for the standard Navigation Window and Tab Group hierarchies. Basic navigation is also easy in Flutter, with super smooth transitions, but you have to create more boiler plate (not so much) to do transitions and there are automatic platform specific transitions, but again on iOS they are emulated and not 100% the same . Also, the standard hierarchies are not supported so well (Tab Group’s are supported, but a little fiddly, and Navigation Window’s don’t easily collapse to the root). Flutter basic navigation has problems such as supporting the Android back button fully and managing a complex stack of windows. A new version, Navigator 2.0, has been developed to deal with these issues, but there is a huge amount of dissent and complaints in the community about how complex the Flutter dev team have made it. The complication is that, for Flutter, navigation has to apply to the web (supporting things like the back and forwards browser navigation buttons) as well as mobile and other platforms. An annoying side-effect is that everything is couched in terms of the very web-centric “routes” and “pages”, rather than screens or windows, but that is a minor grouch.
Theming in Flutter is completely Material Design centric. A lot of theme properties in Material Design are quite obscure and so unless you are from a native Android background and used to using Material Design it can be quite confusing. Also, theming is not iOS friendly, so I roll my own theming for colours and styles. One example are buttons, where I hate the ink well effect on Android/Material Design and prefer the simpler iOS version of button states and so I choose to roll my own for that too.
- General Layout
Layout with both frameworks is pretty straightforward. Flutter has a vast array of layout widgets to help with this such as Row, Column, ListView, Grid and many others. The weird thing, coming from a Titanium background, is that to align an object in some way, instead of setting that as a property (such as left, right, top and bottom) in Flutter you have to nest child widgets in an “aligning” widget. Even padding often requires nesting the widget you want to pad inside a Padding widget. With Titanium it is obviously easier to see layouts schematically in an Alloy view, although you can always examine the Flutter widget tree. Flutter can be a bit more frustrating than Titanium as far as overflowing widgets are concerned, which it shows graphically as an error on screen, but often is difficult to work out why there are issues.
- App Config.
App configuration is easier with Titanium. There is no single file where specific iOS or Android native config can be done, as there is with tiapp.xml (for example Info.plist properties for iOS or Android manifest settings). The config for Flutter has to be done in the respective iOS or Android template projects.
- State Management
Flutter doesn’t do much state management out-of-the-box, but if you want to get more sophisticated there are numerous packages that offer this such as Bloc. State management in Flutter is designed to manage state in a series or stack of widgets. It is more similar to React Native in concept. In all my time using Titanium I never needed any very sophisticated state management, managing with data models and libs and passing data between modules. Backbone handles some of that for you with model and collection syncing.
Events in Flutter are in some ways much more complex, and in some ways much simpler, to use than in Titanium. Events in Flutter are handled by Dart Streams, which are a much more sophisticated model of a sequence of events. Rarely does one use a simple event listener, although some widgets do take an event listener handler as a property. Streams can be complex to grasp and use, although in practice you don’t often have to manipulate them directly and you might do something like pass a stream that a data loader supplies into a ListView, for example. All the complex, background, creating and responding to events is hidden from you.
Well I hope that this article has helped in making a decision as to what to do regarding the future “decommissioning” of Titanium. I believe Flutter is an exceptionally good alternative. At the end of the day no framework is perfect and there are always compromises. You may choose to stick with investing in the Titanium open source movement, but personally I think that is a risky bet (although I certainly will support it moving forward). If anyone would like advice or help in porting their Titanium apps to Flutter please get in touch.
Simon Buckingham is a designer, UX specialist, animator, creative and technical director and developer with more than 20 years experience. He has been making cross-platform iOS/Android mobile apps with Titanium, and more recently Flutter, for more than 10 years. Simon runs his own company Icecandy, based in Winchester, UK. You can find out more about his digital career at simonbuckingham.me.