MMS • Karsten Silz
Silz: My name is Karsten Silz. I want to answer one question in my talk, which is, can we build mobile, web, and desktop frontends with Flutter and one codebase? The answer is yes, we can. I’ll show you. We shouldn’t, because I can only recommend Flutter on mobile. I’ll tell you why.
First, why and how can you build cross-platform frontends? How does Flutter work? I’ll tell you about my Flutter experiences, and then give you some advice on when to use which framework. Who made me the expert here? I did in a sense, because I built a Flutter app that’s in the app stores. I’m also a Java news editor at InfoQ. I help organize the QCon London and QCon Plus tracks on Java and frontend. I know what’s going on in the industry. I’ve also been a Java developer for 23 years. Even though I use Java, Angular, and Flutter, I’m not associated with these projects. I don’t try to sell you books, training courses. I’m not a developer advocate. I’d like to think that I give you options, but in the end, you decide.
Why Cross-Platform Frontends?
Why do we need cross-platform frontends? The reason is because our users are multi-platform. Thirty years ago when I started, I just needed to build a Windows application. These days, we need Mac and Linux, and of course, iOS and Android on mobile. We could try to build with the native SDKs, but that’s too expensive. What we want to do instead is have one framework and one language, and we call that cross-platform. We need cross-platform frontends because they’re cheaper, and they’re good enough. Good enough means good enough for enterprise and consumer apps. I’m not talking about games here. They’ve got separate frameworks. That’s why we need cross-platform frontends because they are cheaper.
How to Build Cross-Platform Frontends
Let me give you an example of why I think native look and feel has advantages. It’s a German online banking app that I use. I had recently started to move from their web version on the left to a native app here on iOS. Why is the native app better here? First of all, on the web version, you need to tap the Hamburger Menu. It’s hard to reach and it’s not obvious, and it’s always two tabs, one for the menu, and then one for functionality. The NavMe on mobile is easy to reach, obvious, and it’s just one tap for the most used functionality. The web application also has these little twisties. I’m not sure my mom would recognize them. That she could actually tap on it. I’m sure she could tap on those big cards on the right-hand side. I think the native app just looks nicer. A native look and feel is important because it looks nicer, and it’s easier to use, because it works like all the other apps on your phone. The Google Apps team agrees with me, because on iOS, they are moving from Material-UI to native iOS UI elements. The responsible Google manager thinks that only with a native look and feel that apps can feel great on Apple platforms. If we do that, we actually have two cross-platform frameworks to juggle, we’ve got web and native, because we keep web for PC, and now we’ve got native for mobile.
I’ve been saying native, but that’s really three different things to me. Number one is it runs natively. It’s in the app stores, and it’s an app. Number two, it’s got a native look and feel. Number three, meaning access to native platform functionality. Given those criteria, what native cross-platform frameworks are out there? There’s a ton and you can find some more on my web page. I looked for open source Java like ones. I’m a Java guy, and I came up with these four: Flutter from Google, React Native from Meta/Facebook, and then Xamarin from Microsoft, which is currently being rewritten as .NET MAUI. It’s supposed to be out in Q2 2022. Then finally, we’ve got JavaFX, which used to be part of Java, but then got open sourced, and it’s now mostly maintained by a company called Gluon.
Which Framework Is Popular?
Which of these frameworks is popular? Why do I care about popularity? A couple of reasons. Number one, a popular technology is easier to use, easier to learn. There’s more tutorials, more training material out there, and more questions and answers on Stack Overflow. It’s also easier to convince your boss and your teammates. I think popularity can make a difference in two situations. If your options mostly score the same, then you could say, let’s go for the most popular one. Or if something is really unpopular, then you could opt to not use their technology. As it just happens, I measure technology popularity in four different ways. First of all, I look at employer popularity. I do that by looking at how often technologies are mentioned in job ads at Indeed. Indeed is the biggest job portal in the world, and I search across 62 countries. Why is that important? If you go ahead and propose new technology in your team, and your teammates rightfully worry, can I find a job? They go to a job portal, and see how many jobs are out there that look for that technology? On the other hand, your boss is worried, can I hire developers for this technology? He also goes and looks in a job portal, because if there aren’t any job ads out there, there may be something wrong with that technology.
Here are the mentions in job ads, going back to August, where React Native had 19,200 mentions, and it now has 25,800. You see these percentages underneath? What do they mean? I use Flutter, the runner-up, as the baseline at 100%. Flutter went from 8,400 to 10,400. We’ve got Xamarin as well going from 5,200 to 5,800. It increased a bit as well, roughly still at 60% of Flutter’s volume. Then JavaFX dropping to about 6% of Flutter’s volume with 600 mentions worldwide. I think the initial two numbers were inflated artificially by wrong measurements on my side. The takeaway here is that React Native added 6,600 adds, whereas Flutter only 2,000. Now I’m looking at developer popularity, how many courses are bought at Udemy, one of the biggest online training sites? Money being spent on courses is another good indicator. It goes back to March of last year. There, Flutter leads, going from 1 million to 3 million students, to 2.1 million. Here, React Native is the runner-up, going from 812,000 to 1.1 million. Xamarin here is a lot less compared to React Native, just about a quarter of its volume.
Then JavaFX on a search recently about plateauing at about 16% of React Native volume. We see Flutter increased by nearly 800k, React Native only by 320k. Another developer popularity measure is Google searches. Starting here, JavaFX peaking in December 2008, and Xamarin the third most popular one peaking in March 2017. React Native as the number two, peaking in July 2019, and Flutter peaking in March 2022. We can see that Flutter has about twice the search volume that React Native has. Last one for developer popularity is questions at Stack Overflow. We can see here JavaFX being number four. It peaked in the end of 2018. Xamarin peaked at the end of 2017. React Native peaked at the end of 2021. Flutter just peaked at the beginning of 2022. We can see that Flutter has about twice the number of questions than React Native. If anything, React Native should probably have more questions, because Flutter is a batteries included framework, and React Native gives you a lot more options and leaves you a lot more freedom. Naturally, you would expect more questions just out of general use, but still Flutter, twice as many questions as React Native. If you want to sum up popularity, employers love React Native, where React Native leads by 2.5x, and it’s pulling away from Flutter. Developers love Flutter, where Flutter leads by 2x, pulling away from React Native. If you’re interested in more technology popularity measurements, in my newsletter, I also measure JVM languages, framework, databases, and web frameworks.
The summary is that web is the biggest ecosystem we ever had with most developers. It’s a bit hard to learn, but we’ve got React, Angular, and Vue as the leading frameworks. For native, meaning running natively, native look and feel, and access to native functionality, we need that on mobile. Flutter is loved by developers, but employers prefer React Native. We also have .NET MAUI and JavaFX, which are less popular. That’s how we can build cross-platform frontends.
How Flutter Works
How does Flutter work? This is DASH, the mascot for Flutter and Dart. Flutter is a Google project, so of course the question on everybody’s mind is, will Google kill Flutter? That’s a hard earned reputation. We’ve got entire websites dedicated to how many projects and services Google killed, here this website counts 266. What’s the answer? Will Google kill Flutter? We don’t know. What’s bad is that Flutter has in-house competition, for instance, Angular. You may not think it but if you look at the Angular web page, for web, mobile web, native mobile, and native desktop. That clearly is very similar to Flutter. It’s confusing. Should I use Angular or should I use Flutter? Then we’ve got Jetpack Compose, which is Flutter for Android. On the plus side, there’s external commitment to Flutter. For instance, Toyota will use Flutter to build car entertainment systems. Canonical uses Flutter to rebuild Ubuntu Linux apps. We also saw that it’s popular with developers, and in second place of popularity with employers. That’s also a plus.
Dart is really only used in Flutter. They both get released together, which means that Google has a chance to tune Dart for Flutter. Let me give you an example of syntactic sugar that Google put into Dart. Here, we’ve got some Dart code, Flutter code to be precise. We’ve got a column with three text fields. If you look closely, then you see we’ve got this, if isAdmin, and it does what you probably expect it does. Only if that isAdmin flag is true, you actually see the password fields, only admins see the password field. Of course, you could do that differently, you could define a variable and then have an if statement. This is more concise, because it’s not separate. It’s used in line here in the declaration. That means it’s more concise, less boilerplate code. Again, that’s an example of syntactic sugar that Google can put into Dart and Flutter.
Libraries are called plugins in Flutter. There’s this portal that you can go to and you see is about 23,000. Most of them are for mobile, not all are for web and desktop. Most of these plugins are open source. There is a good plugin survival ratio. I use many in my app, and over the last year and a half, none of them got abandoned. There’s even a team of developers that takes care of some important plugins if they actually do get abandoned. If something is wrong with a plugin, if you see a bug, or if you want to change it, then you also have the option of just forking it, and then putting the Git repo URL directly in your build file, so it makes it very easy to use a fork of a plugin. UI elements are called widgets. The most important feature here is that widgets are classes. You don’t have a graphical UI builder. There’s no CSS, no XML files. It’s just classes, everything is just attributes and classes and code. That’s really good for backend developers, because that’s the kind of code they’ve always written.
You’ve got to configure widgets. You configure the built-in widgets, mostly, but you can also create your own widgets. The important feature here is that Flutter doesn’t use the native UI element. Instead, it emulates them with a graphic engine called Skia. Skia is used in Chrome, Firefox, and Android. Again, no native SDK UI elements are used because Flutter paints pixels. For look and feel, you get widget sets, and there’s three different categories. The first one is the stuff that you can use everywhere. You’ve got container, row, column, text images. You will use these widgets no matter what platform you’re on. Then you’ve got two built-in widget sets, the Material Design which you can use everywhere, and that’s the native look and feel on Android, and you’ve got the iOS widget set. Then through third party, you get the look and feel on macOS, Windows, and Linux.
Sample Flutter App
I created a sample Flutter app, which has five native look and feel with one codebase. Here’s the sample Flutter app. Here, my sample application is running in an iOS emulator, it is an iOS UI. If I start typing something, then you can see the label disappearing. I got an iOS dialog, but because Flutter just paints pixel, I can switch this over here to look like Android. Now here, as you can see, I can type my name, the label remains and the dialog boxes look like Android. Now I’ve got the sample application running in a web browser, meaning that I’ve got Material-UI with a Hamburger Menu. I’ve got the Material-UI form here with the Material-UI dialogs. Let me do the same thing here. I want to switch over to a Windows look and feel, so now you see on the left-hand side a Windows look and feel and the form fields look different. You can see there’s a different dialog here too. Now I want to switch over to a macOS look and feel. You see it doesn’t work perfectly. There’s something here, a bug, I think it’s a Flutter bug. Now the form here looks different, more like iOS, and the dialog looks different too. That’s all possible because Flutter just paints pixels.
Let me recap what we just saw. We saw five native look and feel, and we could switch between that. We can switch between a look and feel because Flutter just paints pixels, it doesn’t use the native UI elements. You can see that if you dive into the web application, you see everything on the left, you’ve got buttons and a form field. On the right when you look, it’s really just a canvas, which you see down there. Flutter paints pixels. The sample app is on GitHub. How does that switch work? It works probably the way that you expect it to. I created my own widgets. Then each of these widgets has a switch statement, and depending on which platform I’m running, then I create either an iOS, an Android, or macOS, or Windows widget.
When you build a Flutter app, you have to make four architectural choices. The first one is, how do you handle global state in your application? The default way is something called provider. I use Redux, known from the web world in my app. Second is, what kind of widget set do you want to use? Do you use Material, do you use native, do you use custom, or do you mix them? I use native iOS and Android. Routing, there’s a simple router built in called navigator, which is fine for most cases. There’s a more complex one, which you probably don’t need. I use the simple one, the navigator. When it comes to responsive layout, that means to adapt to different screen sizes orientation, there’s nothing built into Flutter. You have to resort to a third party plugin. I use a plugin that takes the bootstrap grid, and applies it to Flutter.
Native integration means two different things. Number one is it means using Flutter in native apps, which works on iOS and Android. The WeChat app is an example here. WeChat is that Chinese app that does everything. A couple of screens were added to this app, and they were built with Flutter, whereas the rest of the application remained in native. That doesn’t currently work for web and desktop. At least for web, it’s under construction. What’s more common is the other way, to use native code in Flutter. You mostly do that through plugins. Stuff like camera, pictures, locations, you don’t have to write native code, because you use a Flutter plugin. Now on mobile, you can also show native screens, and the Google Maps plugin uses that to show you the native iOS and Android screens. You can also have a web view and show web pages in your Flutter app. Finally, you’ve got on mobile, at least a way to communicate with native code through channels, which is asynchronous publish and subscribe. Your Flutter code, your Dart code can call into iOS and Android code, and the other way around. Then there’s even a C API for some more hardcore cases.
If we look at the code, what IDEs can we use? Two are officially supported, IntelliJ/Android Studio and Visual Studio code. Flutter has developer tools, and has a couple of them. The first one is the inspector, which shows you the layout of your application. Then we’ve got the profiler for memory, CPU, and network helping you debug your application. A debugger is there as well. We even have a tool for the junk diagnosis, which means if your application doesn’t run as fluid, doesn’t hit 60 frames per second, you get some help there. The important part is that all of these are not just in an IDE, they also run when you launch your application from the terminal, because they’re built as a Flutter web application so they’re always available.
Project structure is a monorepo, so you get the code for all the platforms in one Git project. You’ve got one folder for Dart, and then one folder per platform. Some of these folders actually contain project for other IDEs. macOS and iOS are Xcode projects. Android is an Android Studio project. Then launching a native application happens through shell files, so you get an app delegate Swift file, or a main activity Kotlin file that kicks off the application.
Flutter has a fast build and deploy. That’s important especially on mobile, because there it’s slow. Deploying your iOS, Android app could easily take 30 seconds, a minute, or even more, just to see your application changes live and an emulator on the phone. Flutter, on the other hand, uses a virtual machine during development. That allows it to do something that’s called hot restart, where within 3 seconds, the entire application gets set back to its starting point. More important, hot reload, where within 1 second, your changes are live and running. That’s really something that keeps you very productive with Flutter, because you can see your changes live, instantly, you don’t have to wait 30 seconds or a minute, like with native development sometimes until your changes are active. I think that’s one of the main reasons why developers like Flutter so much, because within one second, your changes are live.
Let me sum up here. Dart is a simpler Java tuned for UI. Plugins are the libraries. We’ve got a decent amount, and they’re easy to work with. Widgets are the UI elements. You can configure the built-in ones or create your own, and they’re emulated. It doesn’t use the native UI elements. Widget set give you the look and feel. Material and iOS ship with Flutter. We’ve got more like macOS or Windows through third party. On mobile, you can embed Flutter into native apps or use native screens and code in Flutter. Flutter runs natively because it compiles to native code using the platform toolchain. Flutter has great DevTools and gives you a monorepo for all platforms, and has a fast build and deploy on mobile. In the platform check, Flutter only really shines on mobile, lesser on web and desktop. That’s how Flutter works.
My Flutter Experiences
On to my Flutter experiences. I am the co-founder of a startup. We are a B2B software as a service for Cat-Sitters. Our value proposition is that our apps remove friction and save time. I wrote all the code. Here is what it looks like under the hood. The backend is Java with Spring in a relational database. I use Firebase for authentication and file storage. The frontend is an Angular application for the manager, and a Flutter application for the Cat-Sitters. What’s the business case for Flutter? Why did I choose to use Flutter? Number one is I wanted to have unlimited storage and push notifications, so no restrictions here. I wanted the app to be as fast and easy to use as possible, and so I need a native UI for them. Then when I looked at my prototype, and looked at Dart, which is similar to Java and the fast code build and deploy cycle, then I realized I could be very productive with Flutter. That’s why I picked Flutter. Flutter on mobile gets a thumbs up for me. It works as designed, you get two apps for the price of one. It has some minor quibbles, like the similar, it doesn’t always stop the app so you kill it. That’s ok. If something goes wrong, then it’s usually Apple breaking stuff. For instance, I can’t paste from the clipboard into the Flutter app in the simulator for a couple of months now. Apple broke it, and I’m not sure when this will be fixed.
What’s good is that the Flutter team actually listens. A year or two ago, there was some concern on bugs piling up, so Flutter started fixing a lot more bugs. They also have quarterly dev surveys where you can give them feedback. Flutter paints pixels. It emulates, it doesn’t use native UI elements. It works well on iOS and Android, at least. It has some quibbles on iOS. For instance, the list tile doesn’t exist as a widget, so I cobbled together my own using some plugins. The one thing that’s a bit annoying is that when you deal with native UIs, Flutter doesn’t really give you help coordinating that. Because the Flutter team, when you ask them, say, you shouldn’t use native UI, you should customize Material-UI instead. It’s manageable.
Native Look and Feel: iOS vs. Android
Let me give you some examples of the native look and feel in my app, iOS versus Android. First, we’ve got the iOS on the left and Android on the right. If you know your way around these two platforms, then you can see on iOS, we have the button in the upper, whereas on Android, we have a floating action button. The iOS has a list indicator, whereas Android doesn’t have that. Here are some detailed screens from iOS. This one here is a recent addition, the animated segment control that took a couple of months until it showed up in Flutter because it needed to be added to the library. Then down here, I told you that there is no built-in list tile for iOS, so this is the custom control that I created based on some plugins and some customization on my own. Then finally, here, we see some buttons. They are the same on Android. This is a place where I use my own design, not using native buttons.
I also give a thumbs up to Firebase. What is Firebase? Firebase is Google’s backend as a service on mobile, web, and server. It’s got mostly free services like authentication and analytics, and some paid features like database or file storage. Especially on mobile, it’s helpful because it gives you one service instead of two. For instance, crash logging and test version distribution, both iOS and Android have their own version. Instead of using these two separate services, you just use the one Firebase service. It works good, and has good Flutter integration. You’ll find some more stuff on my talk page, for instance, how to use the power of mobile devices. How to keep UI cracked with one source of UI truth. How you could be consistent between your web app and your mobile app. How back to basics also applies to mobile apps. These are my Flutter experiences.
Let’s just sum up what we’ve heard so far. Why do we need cross-platform frontends? We need them because they are cheaper, and good enough. How can we build cross-platform frontends? The default answer is web because it’s the biggest software ecosystem ever with the most developers. React, Angular, Vue are popular frameworks. We need native, running native, native look and feel, and access to native functionality, especially on mobile. Developers like Flutter, employers prefer React Native. Then there’s .NET MAUI, and JavaFX a lot less popular. We also talked about how Flutter works. Dart is a simpler Java tuned for UI. Plugins are the libraries, easy to work with. Widgets are the UI elements, they’re emulated. The widget set give us the look and feel. Material and iOS ship with Flutter. We can get other through third party plugins. Native means access to all native functionality on mobile, which is a plus. Flutter runs natively because it compiles to native code with platform toolchains. It’s got great DevTools, a monorepo for all platforms, and got fast build and deploy on mobile. Flutter really only shines on mobile, lesser on web and desktop. My Flutter experiences, the business case was to overcome restriction, have a fast UI, and be productive. Flutter works, two apps for the price of one. Flutter paints pixels, also works. Firebase is also good because it offers free and paid services, which means one service instead of two separate ones on mobile. It also works.
Flutter vs. World
If you want to find the slides and the videos, additional information, the native UI sample app, want to get started with Flutter, links to tutorials and other information, or you want to get feedback, subscribe to my newsletter, then you head to this link, bpf.li/qcp.
Questions and Answers
Mezzalira: Have you ever played with Dart, server side?
Silz: I have not. I’m a Java guy. That’s just a much bigger ecosystem there. No comparison. I think there are some that do Dart on the server side, but there are also people that use Dart for other frameworks. I wouldn’t recommend it. There’s much better options on the backend.
Mezzalira: Knowing the power of Java and the Java community I can understand.
You talk about how Flutter is gaining traction at the developers’ level. What about organization level? Can you share your point of view on how the C-suite would think about Flutter, especially, obviously the technical department? If it has a nice penetration for developers.
Silz: I think there’s probably three things here. Why do people want to hire React Native developers a lot, but when you look at developers, they prefer Flutter? I think there’s three reasons here. Number one, is that if you’re using React on your project, and a lot of people do, then I think React Native as a mobile framework does make sense. That’s what I’m recommending. I think there’s some push from that perspective. The second thing is, I think people are just wary about Google stuff. I hear that often when I talk about Google or a Google project. They say, when are they going to abandon it? There’s a reason why these web pages are out there. I think people are a little bit wary. Then they look at Facebook, and they say, Facebook has React and React mobile, so they can’t kill it, because then they can’t build their apps anymore. The third reason is that Flutter explicitly says, we want to have a great dev experience. Smartly, they published their roadmap for the year and they said, nobody has to use Flutter, because there’s the built-in base options there. There’s other frameworks out there. We have to give developers a great experience so that they actually want to use Flutter. That’s why they put a lot of money into tools. I think that pays off. I think the tool side is probably stronger than what you get on React Native.
Mezzalira: How do you feel about Flutter supporting all the feature changes from the UI style on iOS and Android?
Silz: The background is, as I said, Flutter doesn’t use the native UI set. It uses emulation, so it has to paint everything itself. I think the answer there is threefold. Number one, I’m feeling really good about Material, because the Material stuff is Google’s own design language. They recently went through some changes. It used to be called Material Design. Now it’s Material You, and there are some changes. The Flutter team already said, we’re bringing these changes in there. I think, no worry about the Google Material Design language. It’s got the home turf advantage. On the iOS UI set, or widget set on iOS and iPadOS, ok. There hasn’t really been a big change there. The only thing is they made some changes, left some smaller changes, they came into the widget set as well. For instance, there was an animated segment control. In the past, you had that stay with one and then the animated one where the slider moves around. That took a couple of months, but it’s there. Now, if iOS ever makes a big UI redesign. I think probably, yes, as well. It may take a while. I think where I’m most worried about is the third party ones, the macOS and Windows ones. Those are hobbyists. They’re currently not complete. On macOS, there’s no dropdown in those widget sets. That’s where I’m most worried about. Will they ever be complete, and will they remain up to date? Because both of these UI elements, the macOS and Windows, they are somewhat in flux. That fluent, modern design of Windows still developing, and macOS still going through some changes there, too.
Mezzalira: Does Flutter repaint the entire UI for a small change? If yes, wouldn’t this be a costly operation?
Silz: The answer is no. Flutter has change detection. What Flutter does under the hood, it’s a declarative framework, the same way that React Native is, or SwiftUI, or Jetpack Compose, and .NET MAUI. What it means is that in your UI, you say my widgets. In my text field, I have this text, and this text, the state of that comes from a variable that I declare. If you then change this variable, and you enclose that in a set statement, then Flutter knows, ok, the state of the UI has changed, and now I need to repaint the UI. It knows because you only change that one variable that only the UI elements that use that one variable, they need to be repainted. I think there’s no worry there. I noted in other frameworks I sometimes hear like with React maybe that things can get out of hand, change detection and repainting, and stuff. Flutter has got that really well down. You don’t see your UI really becoming very stuttery. The only time that you see some stutter, typically is when you get to a new page, and you start loading data. Because as I said, everything happens, Flutter is single threaded. Unless you do something special, everything happens on the main thread, and so to keep the 60 frames per second you have to be a bit careful. I think in my app, for instance, occasionally, it stutters a bit if I open a list, and there’s 100 elements on there. If I were to pay more attention, put some work into it, that could be fixed as well.
Mezzalira: How much can we fine-tune the UI? How easy is changing behavior and styles?
Silz: It’s different from the web. In the web the solution would be to use a style sheet, and change that style sheet and reference it. There is no equivalent in these frameworks for that, because everything is code. My recommendation would be to create your own widgets. You create your own text field. You create your own button. I even have pages created, where I said, here’s a page, and it’s got an edit button, for instance. Then you’ve got one central component that you have to configure. If you want to change your theme or change your style, you would then go and change all your components. Of course, then you can get smart and say, I’ve got a class that tells me what colors to use, or what font size to use, and all your widgets use that. Recommendation is build your own widgets that just wrap the widgets that you want to use, and then you apply the styling configuration in your own widget. Then you’ve got one central point to change that, because as with all the other frameworks, there is no extra style sheet config file, property file where you can make these global changes. You have to do them in the code, so just the regular ways of making changes across all your classes apply.
Change detection is different from Angular. In Angular, you can just change your state, and angular figures out what changes. In Flutter, you have to make an explicit set state around your state changes to force that state change. That’s a difference that I find from Angular. Angular you just change your variable and Angular repaints it. In Flutter you do a set state, and then you put your state changes in that statement.
See more presentations with transcripts