Production Flutter'ing
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Friedrich, Matthias
End of 2017 we were about to start work on a completely new app that should lay ground for our whole companies mobile app strategy for the years to come. We decided to join forces of our two existing native mobile app developer teams and use Flutter Google’s new cross-platform framework for Android and iOS. Advantages like really well working hot-reload complete code sharing for both platforms and a modern reactive ui framework are just too good to be ignored. But Flutter is still in an early state and with that has its teething troubles and also very own shortcomings. In the first part of this talk I want to share the overall experience we made building our very first Flutter app and running it in production for over 3 months. The second half then goes full into live coding mode to show one of Flutter’s strengths: the easiness to build a fully customized animated graph the visual highlight of our still small but beautiful app. After the talk you hopefully have a better picture of what Flutter is capable of its state of maturity and which use-cases it’s already great to be taken for.
 All right. So welcome after the short way too long break. I'm Matthias Friedrich and I want to talk about our experience building our first Flutter app at Jimdo. First a little bit about myself. I'm an Android developer since 2009, directly when I could get my first hands on a real device back then the first time in the galaxy. Since then I worked on lots of apps. Hybrid apps, featured native apps in the Play Store, even completely custom Android software for custom environments. And as I am a real die-hard Android developer in Zen, I was never convinced by any solution that went cross-platform or hybrid. But yeah, let's go on. And it has some reasons that I was never convinced. So especially when native developers see cross-platform, hear cross-platform, they think, yeah, that can't be it because there are several reasons. For example, cross-platform applications often don't feel native. The UI doesn't feel like it should on an Android device or on iOS device. It often feels wrong. Then there's often when the cross-platform framework uses native UIs under the hood, it needs to bridge the development language that the developer is building the app into the native development tools. And that creates an update gap. For example, when Google or Apple are updating the native SDKs. So it takes time until latest UI features are available into these new cross-platform tools. The same is valid for hardware integrations. When you, for example, want to approach an NFC reader or something like that, it takes time until these things are valuable to the cross-platform development tools. And of course, another big disadvantage cross-platform tools often have is that the performance is just bad. It's depending on how they are done exactly under the hood. They need to bridge to the native development tools. They often depend on JavaScript that is being interpreted and with that doesn't run as fast as a native compile code. And all this then results in bad developer experience. And this then is often the result. So you have to choose. Go real native, build lots of complex things for the different platforms, but have a really good outcome, a shiny castle, or do some cross-platform tool and the result will, yeah, not as good. Will be not as good. But okay, some more context regarding us. We are Jimdo. Our main product is a website builder, so our main product with that out of the nature of the product is in the web. But we still have several native applications for Android and iOS. These four. And the biggest one, the creator has more than 1.2 million installs on each of the platforms and we got featured by the Play Store. So yeah. But we still are two developers inside the team. Why two? Because our management first thinks that small teams can move really fast and that's what they want. And our main money driver are not these apps. So the reason why we are building mobile apps is to push the brand awareness from within the app stores and also to upsell our products. So with the mobile apps giving additional features to our core product, the website builder, but also to engage our users when they are out, when they are mobile. For example, giving shop notifications about the online shop and so on. Yeah. And we have a really progressive culture at the company. Our management constantly tells us to move fast, to break things. They want to push us to use new development tools that are promising. Yeah. And so we went ahead and we wanted to build a new app for our, we internally changed the whole product, moved away from our old legacy product and moved to a new one and for that we wanted to build a completely new app as well. And that was Jim to boost. A new companion app for website owners in our system. And we knew from the start that this app would be not dependent on deep system integration like NFC readers, Bluetooth location awareness and so on. So our app is mainly about giving people, showing people content out of our system. So basically from our backend. And also as our main users, or for this app, all our users actually are using our app product anyway, we wanted to not focus on platform specific UI and design, but to push our brand and bring our brand design which we created over the last two years into mobile as well. Before we didn't do that, especially because we were just two developers per platform, we said we keep it to the platform to be consistent. Yeah. So all this sound as good reasons to try a cross-platform solution. And then, yeah, there was Flutter around. It was end of last year when Flutter was still in alpha. And of course it has the promise to write once and one on several platforms. And it features a really new, modern, reactive and highly customizable UI framework. And that was really promising, especially regarding our intent to push our brand design instead of the platform. And yeah, it promises really fast development with hot reload. And what I especially like personally about it is that it has, although it's cross-platform, it has native UI performance and it's completely platform independent on the UI stack. So when you build a Flutter app, whatever you do there, it will and look exactly the same, be it a Samsung device running Android 4.1, even Samsung, we know there are lots of troubles with Samsung, or be it a pixel running latest Android P. The Flutter app will always look and behave exactly the same. Same for when they are running on iOS devices. Yeah, but it uses Dart, so Dart was new to us. So we had a look at that. Dart is fully open source. The complete project, even the standard, is an ECMAS standard. So it's completely open. And it's around since 2011. So it has some really matured unstable core libraries. And on the language side, it has something modern approaches like lambdas, some nullability features like the Elvis operators. But in general, the language feature-wise, I would say, is between Java and Kotlin. The good thing is that you can run it in two ways. So it can be compiled just in time. So meaning, run it, put it on the device, it gets compiled directly on runtime. And that means Flutter can use this feature to directly swap out the code that is running inside the app, which is hot reload. But it can also compile ahead of time to our native binaries. And that means it does that as soon as you build the app for production. And that means production builds are really fast and smooth. So Flutter apps have kind of become known for being really smooth. Yeah, and this is what, for example, a Google suffer engineer who didn't came from the Dart team said about Dart. He would like it to be a bit more feature-rich, that it can do more, for example, like Kotlin. But he had to say that he was directly productive after a day. And we in our team, we felt the same. So Dart is that simple when you are coming from JavaScript, from Swift, from Java, from Kotlin, from TypeScript, you feel immediately at home. Because it's so easy, it focuses on familiarity instead of really big, complex features. And that makes it really easy to use. So for example, if it really catches up, that can be a main driver for hiring people. Because you can hire whatever guy you want, or woman, whatever person you want, sorry, whatever person you want. And it can be someone from web development doing JavaScript, from iOS development, from Android development, they will feel comfortable. So we went ahead and built our app, the Jimbo boost app. How does the GIF perform there? Copy better on this machine? Okay. You don't see how smooth it is. How old is this? Okay. Anyway. Yeah. As you can see, we built some really custom UI there. It features our brand design, our Jimdo design, as we call it. And yes, there are some similarities, of course, to iOS and to Android as well. But yeah. People that use this are going from our web product. And when they see this, they directly feel at home. That was our goal. It's still very small and simple. It doesn't do much yet. But it's just a start and most valuable product for what we do for our new product. And so far, it's just showing some simple statistics about how the websites are being visited. But yeah, we have way more things planned for this app. And we're going to proceed with Flutter. So we are how we approached it. We took Flutter for a test for two weeks with our four developers, built a small prototype. And in this prototype, each of our developers was meant to check out some certain features that we know are important for us that we need to be working so Flutter is a new blocker for us. And so we thought, there wasn't a big blocker, so we went ahead and built this app in roughly three months, including a completely new backend and approaching three different backend APIs. And also some conceptual back and forth with what the app should actually do. So yeah, it's maybe a bit hard to tell how productive we were with Flutter in these three months. But when we started, it was still in alpha. And with that, we had several smaller hiccups with Flutter. But it's still nothing really big blocking. One small thing was, for example, that on iOS devices, in certain configurations of iOS, the Flutter system always provided the language English back to the Flutter app, although the device was configured to a different language. But as Flutter is made out of building blocks that are interchangeable, and you can really customize everything, you can exchange the whole localization system that the framework uses. So we wrote our own little tool there, our own little localization feature that used the Flutter platform channels, went to the native side of Android, checked the language there and delivered that back to the app. And that was done in like half an hour before we even checked out if the issue was already on the GitHub repository, on the GitHub project of Flutter. So yeah, it's really easy to do. And you can be really fast with it. And things like that will come up, but they're not really blockers because the system is so open that you can exchange everything. Yeah, in general, feedback from our team, our Android developers loved it immediately because they feel directly home with the tooling, IntelliJ, and Android Studio. And the results were also, before we even styled something, immediately nice for our Android developers because per default, it looks like material design. But our iOS developers didn't love it as much at the beginning, but they're starting to as well. But yeah, at first, the tooling was unknown to them, coming from Xcode, getting into IntelliJ or Android Studio. And of course, the default was material designs. And that's also not directly what they wanted to have. But yeah, they are getting into it one more as well because they see they are really productive with this framework. And also, we even had some applicants that just applied to our company because we said we are using Flutter already. So that can also be some good thing in the future. And one thing we saw really usable when working with this new tool, and we had iOS developers and Android developers, is when, for example, the Android developers are developing some feature, let it be reviewed by the iOS developers. So they can check on their device as well and can also see if it's fine with how it works on iOS. Yeah, okay. Now I want to go ahead a bit and cover some topics that you're going to approach when you would go beyond a Hello World project in Flutter. So for example, how to approach REST APIs. Every app has to do that basically. On Flutter, there's nothing like reflection. On Dart with Flutter, there's nothing like reflection. Dart itself has reflection, but it's not supported by how apps are being compiled for Flutter. But there is something like the Jaguar tool suite. It's roughly similar to how is it called Retrofit and GSON. Of course GSON uses reflection for Java, but Jaguar works a bit different. It's a Dev Time tool, so you have to put your mapping code, put your model code into the tool and generate some mapping code that you can use inside the tooling done. On Dart. Some other topic. We didn't use Jaguar. We went ahead and wanted to use Swagger because we in the mobile team had to build our own backend for this app. And Swagger is a tool where you can define a model and it generates basically the interfaces for the backend as well as for the clients. But yeah, there was support for Dart already in Swagger, but it was based on Dart mirrors, which is reflections. So it works with Dart web clients, but not with Flutter. So we worked the whole code generation for Dart in Swagger, and then we were good to go and build our backend with this and you're free to use it now as well. So yeah, it's now inside the project. Some other thing I would want to highlight is the versioning of Flutter itself. Flutter itself, when it's installed or checked out, it's just a Git repository on a machine, twice is checked out out of Git for one specific version of Flutter. So each project you have on your machine then gets built against this specific Flutter version. That's of course not what you want when you have several projects that you need to maintain. You don't want to keep them all updated immediately for each SDK version that comes along. And it's really bad when you share codes between several people and they're working on the code. So to really have stable builds there, you need to pinpoint to one specific Flutter version that the project gets built against. We had it several times that some other developer that was gone for a few days then came back and the app didn't build anymore or behaved weirdly because his SDK version was outdated. So there's Pascal Welch, GDE actually for Flutter who built this project, Flutter wrapper, just like the Gradle wrapper. And it pinpoints a specific Flutter SDK version to the project and then downloads checks out from Git from GitHub this specific SDK version when you try to build it. So especially when you work with several people and the CI use this. Then crash reporting. So there's no crash-lit support yet which is a bit sad because both is from Google. You could imagine that they would be talking to each other but it's not there yet. And the only SDK for crash reporting we found yet was Sentry IO. Of course you can use whatever tool you want and do your HTTP request with the crash data to that tool on your own. But we didn't want to write that on our own so we looked for an SDK, we found Sentry. But this one is also really simple SDK. It just gives you some methods to send something over to Sentry by providing an API key basically. But there's nothing like on Android where you just have to add the plug-in to the project and it will take care on its own to crash errors, to lock errors, to catch them actually. So we went ahead and had a look what do we need to do to catch exceptions on Dart. What we found is basically this. Flutter error.onerror you just set your listener there and it will get called for errors that are happening in the framework. And from there we just call our own error handler and reported back to Sentry. Yay, done, easy. So we released that and after two weeks or something we thought there weren't any crash reports. So that can't be. It would be cool but yeah, that can't be. So we had a look again at the documentation and what it says was called whenever the Flutter framework catches an error. What does it mean? So of course when we saw it for the first time we guessed yeah, that's fine. But it isn't. It's really just when some call from inside the framework crashes. So your own Dart code with classes not directly running inside the framework won't be catched by that. So after some digging on Stack Overflow we found this basically. So you have to run the whole Flutter app. As you know, everything on Flutter is a widget. So also the whole app is run it's zoned basically and that wraps the whole widget basically inside an error handling. So we are now logging in from there and we saw some crash logs actually. Damn it. But okay. Our error handler looks actually like this. So when it's a release build we log it to Sentry. But what's more interesting here is that also when it's a release build and it's not an exception that comes from somewhere out of background processing, then we directly close the app. So in that case we know the crash happened somewhere in the foreground is highly possible, highly possibly UI related and with that can create a state for the user that we don't want to leave the user in. Because Flutter on its own when it crashes it doesn't crash the app. The app doesn't close. Instead it shows something like this. So that's really cool for debugging but you don't want to show that to the user of course. So that's why, yeah, that's why we, when we see it's not a background error that does something unpredictable with the UI we close the app. Of course you want to keep that in debugging. So that's why we came up with the solution because in debugging when you use hot reload and you try out some code, put it on the device, you see this because it didn't run, you can maybe directly see what was the problem, change the code directly, press hot reload again and this will just go away and that will proceed where it was before. Yeah, okay, the biggest thing I personally think is a blocker for Flutter itself is that there is no background execution of Dart code yet. So when there's no screen around, no activity, you cannot execute any Dart code. It always needs a screen. And with that when you for example get push notifications on Android it's quite common that you get a push notification, you talk to your persistence or to your backend even, get some data and then show the notification actually depending on the data of the user. This way you can't do that. You can do push notifications but just when they are completely defined by your backend. With some simple actions that directly go into your app. For example, custom actions on notifications are also not possible because you cannot execute something in the background. They are working on this but as a tip, keep your users data maybe on native side you want to use the account manager anyway. So more things are like CI, we're using traffic CI with fast line that works quite good out of the box. Of course on iOS it's a bit more complex with the signing there but it works quite good. Then testing, Flutter supports unit tests, which are tests and which are tests are really good because they are basically testing your UI like a unit test. So you can unit test your UI because your UI is basically an immutable tree out of widgets and you can just test what data is inside these immutable objects like a unit test. But there is also integration test where you can run it on a real device and instrument the UI. Integration was the biggest problem we had actually because the tooling for localization is a bit sad I would say because you have to write Dart code that defines your strings, run this through a tool that will generate some template files. You have to use this template files to create your own string files. Take all the string files, run it through a tool again which generates Dart code and you can put it into your app. So no one wants to do that. Especially when you are coming from Android for example where you just have the string XMLs. So we created our own system which is based on JSON and which just does some simple parsing for Pluel or for placeholders. We didn't open source that yet but there is some good medium article that describes exactly that as well. So someone else came up with it as well. So as I'm short on time now, mobile apps with Flutter regarding non-native UI on Android for example, material design is native, same on Flutter so you will be covered. For iOS it's a bit more difficult because you have to then do some ifs inside your UI code and maybe use a different widget that then looks like iOS. They are also inside the Flutter framework but you have to invest a little bit coding there. Then about the feature and update gap, it's maintained by Google and even Flutter is the first target now for the material design team so when the material design team at Google comes up with something new, Flutter is the first target to implement it in now. Then regarding system integrations for hardware integration for example, there are platform channels and these are really easy to use. They are basically like a JSON interface but it's really easy to set up. It's directly integrated into the native side of your code that gets generated when you create a new project so inside the Flutter activity where the whole app is running in and there's also directly some APIs to use it on the Flutter side. Then regarding bad performance, when you build for production it's compiled to native so it can possibly even be faster than apps built against the Android SDK because apps against the Android SDK are shipped in byte code and byte code always runs on a VM. This is directly running on the machine. Hot reload is really a game changer. The Android team also tried to do that with Instant Run but I personally always turn it off because you never know when it works and when not. This thing just works. It's really a game changer for when you are working with Flutter. I would actually say it more looks like this then. For Flutter you can build something that is not as complex to do anymore as pure native. Of course when you want to be really sophisticated and integrated with the system features you will have to go a bit extra but overall the result will be quite like the native application I would say. And that's how I personally felt after using Flutter and coming back to our native apps that we are still maintaining. So I really felt like what's going on here. It's so damn slow. It felt like working with my hands bound behind the back. It was like what the heck is this really how I worked before? So Flutter is really damn fast in development. So you are really productive with it. I actually wanted to do some live coding still but I guess time is out now. So yeah, thanks a lot. And yeah, I have to say this we are hiring as well. So when you want to do Flutter approach me. And yeah, otherwise thanks a lot. I don't have my Android Studio here anymore. Otherwise I would show some code actually. Yes. Are we good to go? We have two microphones over there. Thank you. Thank you for your talk. Do you have any kind of approach how we can integrate C++ libraries in Flutter projects without maybe channels? Yeah, so far there's no direct integration. I just looked it up myself yesterday because I really like Object Box and Object Box is directly doing C++. So I looked how to do Object Box with Flutter but there's no way yet. They don't have, of course it should be possible somehow but you have to dig really deep to make that running. So the only advice they give now is go platform channel and from the activity go C++. But yeah, then I mean you do the bridging again across Java that doesn't make sense when you go native. But they're working on it. More questions. Seems not. Okay. Thank you.
 All right.  So welcome after the short way too long break.  I'm Matthias Friedrich and I want to talk about our experience building our first Flutter  app at Jimdo.  First a little bit about myself.  I'm an Android developer since 2009, directly when I could get my first hands on a real  device back then the first time in the galaxy.  Since then I worked on lots of apps.  Hybrid apps, featured native apps in the Play Store, even completely custom Android software  for custom environments.  And as I am a real die-hard Android developer in Zen, I was never convinced by any solution  that went cross-platform or hybrid.  But yeah, let's go on.  And it has some reasons that I was never convinced.  So especially when native developers see cross-platform, hear cross-platform, they think, yeah, that  can't be it because there are several reasons.  For example, cross-platform applications often don't feel native.  The UI doesn't feel like it should on an Android device or on iOS device.  It often feels wrong.  Then there's often when the cross-platform framework uses native UIs under the hood,  it needs to bridge the development language that the developer is building the app into  the native development tools.  And that creates an update gap.  For example, when Google or Apple are updating the native SDKs.  So it takes time until latest UI features are available into these new cross-platform  tools.  The same is valid for hardware integrations.  When you, for example, want to approach an NFC reader or something like that, it takes  time until these things are valuable to the cross-platform development tools.  And of course, another big disadvantage cross-platform tools often have is that the performance is  just bad.  It's depending on how they are done exactly under the hood.  They need to bridge to the native development tools.  They often depend on JavaScript that is being interpreted and with that doesn't run as fast  as a native compile code.  And all this then results in bad developer experience.  And this then is often the result.  So you have to choose.  Go real native, build lots of complex things for the different platforms, but have a really  good outcome, a shiny castle, or do some cross-platform tool and the result will, yeah, not as good.  Will be not as good.  But okay, some more context regarding us.  We are Jimdo.  Our main product is a website builder, so our main product with that out of the nature  of the product is in the web.  But we still have several native applications for Android and iOS.  These four.  And the biggest one, the creator has more than 1.2 million installs on each of the platforms  and we got featured by the Play Store.  So yeah.  But we still are two developers inside the team.  Why two?  Because our management first thinks that small teams can move really fast and that's what  they want.  And our main money driver are not these apps.  So the reason why we are building mobile apps is to push the brand awareness from within  the app stores and also to upsell our products.  So with the mobile apps giving additional features to our core product, the website builder,  but also to engage our users when they are out, when they are mobile.  For example, giving shop notifications about the online shop and so on.  Yeah.  And we have a really progressive culture at the company.  Our management constantly tells us to move fast, to break things.  They want to push us to use new development tools that are promising.  Yeah.  And so we went ahead and we wanted to build a new app for our, we internally changed the  whole product, moved away from our old legacy product and moved to a new one and for that  we wanted to build a completely new app as well.  And that was Jim to boost.  A new companion app for website owners in our system.  And we knew from the start that this app would be not dependent on deep system integration  like NFC readers, Bluetooth location awareness and so on.  So our app is mainly about giving people, showing people content out of our system.  So basically from our backend.  And also as our main users, or for this app, all our users actually are using our app product  anyway, we wanted to not focus on platform specific UI and design, but to push our brand  and bring our brand design which we created over the last two years into mobile as well.  Before we didn't do that, especially because we were just two developers per platform,  we said we keep it to the platform to be consistent.  Yeah.  So all this sound as good reasons to try a cross-platform solution.  And then, yeah, there was Flutter around.  It was end of last year when Flutter was still in alpha.  And of course it has the promise to write once and one on several platforms.  And it features a really new, modern, reactive and highly customizable UI framework.  And that was really promising, especially regarding our intent to push our brand design  instead of the platform.  And yeah, it promises really fast development with hot reload.  And what I especially like personally about it is that it has, although it's cross-platform,  it has native UI performance and it's completely platform independent on the UI stack.  So when you build a Flutter app, whatever you do there, it will and look exactly the  same, be it a Samsung device running Android 4.1, even Samsung, we know there are lots  of troubles with Samsung, or be it a pixel running latest Android P. The Flutter app  will always look and behave exactly the same.  Same for when they are running on iOS devices.  Yeah, but it uses Dart, so Dart was new to us.  So we had a look at that.  Dart is fully open source.  The complete project, even the standard, is an ECMAS standard.  So it's completely open.  And it's around since 2011.  So it has some really matured unstable core libraries.  And on the language side, it has something modern approaches like lambdas, some nullability  features like the Elvis operators.  But in general, the language feature-wise, I would say, is between Java and Kotlin.  The good thing is that you can run it in two ways.  So it can be compiled just in time.  So meaning, run it, put it on the device, it gets compiled directly on runtime.  And that means Flutter can use this feature to directly swap out the code that is running  inside the app, which is hot reload.  But it can also compile ahead of time to our native binaries.  And that means it does that as soon as you build the app for production.  And that means production builds are really fast and smooth.  So Flutter apps have kind of become known for being really smooth.  Yeah, and this is what, for example, a Google suffer engineer who didn't came from the Dart  team said about Dart.  He would like it to be a bit more feature-rich, that it can do more, for example, like Kotlin.  But he had to say that he was directly productive after a day.  And we in our team, we felt the same.  So Dart is that simple when you are coming from JavaScript, from Swift, from Java, from  Kotlin, from TypeScript, you feel immediately at home.  Because it's so easy, it focuses on familiarity instead of really big, complex features.  And that makes it really easy to use.  So for example, if it really catches up, that can be a main driver for hiring people.  Because you can hire whatever guy you want, or woman, whatever person you want, sorry,  whatever person you want.  And it can be someone from web development doing JavaScript, from iOS development, from  Android development, they will feel comfortable.  So we went ahead and built our app, the Jimbo boost app.  How does the GIF perform there?  Copy better on this machine?  Okay.  You don't see how smooth it is.  How old is this?  Okay.  Anyway.  Yeah.  As you can see, we built some really custom UI there.  It features our brand design, our Jimdo design, as we call it.  And yes, there are some similarities, of course, to iOS and to Android as well.  But yeah.  People that use this are going from our web product.  And when they see this, they directly feel at home.  That was our goal.  It's still very small and simple.  It doesn't do much yet.  But it's just a start and most valuable product for what we do for our new product.  And so far, it's just showing some simple statistics about how the websites are being  visited.  But yeah, we have way more things planned for this app.  And we're going to proceed with Flutter.  So we are how we approached it.  We took Flutter for a test for two weeks with our four developers, built a small prototype.  And in this prototype, each of our developers was meant to check out some certain features  that we know are important for us that we need to be working so Flutter is a new blocker  for us.  And so we thought, there wasn't a big blocker, so we went ahead and built this app in roughly  three months, including a completely new backend and approaching three different backend APIs.  And also some conceptual back and forth with what the app should actually do.  So yeah, it's maybe a bit hard to tell how productive we were with Flutter in these three  months.  But when we started, it was still in alpha.  And with that, we had several smaller hiccups with Flutter.  But it's still nothing really big blocking.  One small thing was, for example, that on iOS devices, in certain configurations of  iOS, the Flutter system always provided the language English back to the Flutter app,  although the device was configured to a different language.  But as Flutter is made out of building blocks that are interchangeable, and you can really  customize everything, you can exchange the whole localization system that the framework  uses.  So we wrote our own little tool there, our own little localization feature that used  the Flutter platform channels, went to the native side of Android, checked the language  there and delivered that back to the app.  And that was done in like half an hour before we even checked out if the issue was already  on the GitHub repository, on the GitHub project of Flutter.  So yeah, it's really easy to do.  And you can be really fast with it.  And things like that will come up, but they're not really blockers because the system is  so open that you can exchange everything.  Yeah, in general, feedback from our team, our Android developers loved it immediately  because they feel directly home with the tooling, IntelliJ, and Android Studio.  And the results were also, before we even styled something, immediately nice for our  Android developers because per default, it looks like material design.  But our iOS developers didn't love it as much at the beginning, but they're starting to  as well.  But yeah, at first, the tooling was unknown to them, coming from Xcode, getting into IntelliJ  or Android Studio.  And of course, the default was material designs.  And that's also not directly what they wanted to have.  But yeah, they are getting into it one more as well because they see they are really productive  with this framework.  And also, we even had some applicants that just applied to our company because we said  we are using Flutter already.  So that can also be some good thing in the future.  And one thing we saw really usable when working with this new tool, and we had iOS developers  and Android developers, is when, for example, the Android developers are developing some  feature, let it be reviewed by the iOS developers.  So they can check on their device as well and can also see if it's fine with how it  works on iOS.  Yeah, okay.  Now I want to go ahead a bit and cover some topics that you're going to approach when  you would go beyond a Hello World project in Flutter.  So for example, how to approach REST APIs.  Every app has to do that basically.  On Flutter, there's nothing like reflection.  On Dart with Flutter, there's nothing like reflection.  Dart itself has reflection, but it's not supported by how apps are being compiled for Flutter.  But there is something like the Jaguar tool suite.  It's roughly similar to how is it called Retrofit and GSON.  Of course GSON uses reflection for Java, but Jaguar works a bit different.  It's a Dev Time tool, so you have to put your mapping code, put your model code into the  tool and generate some mapping code that you can use inside the tooling done.  On Dart.  Some other topic.  We didn't use Jaguar.  We went ahead and wanted to use Swagger because we in the mobile team had to build our own  backend for this app.  And Swagger is a tool where you can define a model and it generates basically the interfaces  for the backend as well as for the clients.  But yeah, there was support for Dart already in Swagger, but it was based on Dart mirrors,  which is reflections.  So it works with Dart web clients, but not with Flutter.  So we worked the whole code generation for Dart in Swagger, and then we were good to  go and build our backend with this and you're free to use it now as well.  So yeah, it's now inside the project.  Some other thing I would want to highlight is the versioning of Flutter itself.  Flutter itself, when it's installed or checked out, it's just a Git repository on a machine,  twice is checked out out of Git for one specific version of Flutter.  So each project you have on your machine then gets built against this specific Flutter version.  That's of course not what you want when you have several projects that you need to maintain.  You don't want to keep them all updated immediately for each SDK version that comes along.  And it's really bad when you share codes between several people and they're working on the  code.  So to really have stable builds there, you need to pinpoint to one specific Flutter version  that the project gets built against.  We had it several times that some other developer that was gone for a few days then came back  and the app didn't build anymore or behaved weirdly because his SDK version was outdated.  So there's Pascal Welch, GDE actually for Flutter who built this project, Flutter wrapper,  just like the Gradle wrapper.  And it pinpoints a specific Flutter SDK version to the project and then downloads checks out  from Git from GitHub this specific SDK version when you try to build it.  So especially when you work with several people and the CI use this.  Then crash reporting.  So there's no crash-lit support yet which is a bit sad because both is from Google.  You could imagine that they would be talking to each other but it's not there yet.  And the only SDK for crash reporting we found yet was Sentry IO.  Of course you can use whatever tool you want and do your HTTP request with the crash data  to that tool on your own.  But we didn't want to write that on our own so we looked for an SDK, we found Sentry.  But this one is also really simple SDK.  It just gives you some methods to send something over to Sentry by providing an API key basically.  But there's nothing like on Android where you just have to add the plug-in to the project  and it will take care on its own to crash errors, to lock errors, to catch them actually.  So we went ahead and had a look what do we need to do to catch exceptions on Dart.  What we found is basically this.  Flutter error.onerror you just set your listener there and it will get called for errors that  are happening in the framework.  And from there we just call our own error handler and reported back to Sentry.  Yay, done, easy.  So we released that and after two weeks or something we thought there weren't any crash  reports.  So that can't be.  It would be cool but yeah, that can't be.  So we had a look again at the documentation and what it says was called whenever the Flutter  framework catches an error.  What does it mean?  So of course when we saw it for the first time we guessed yeah, that's fine.  But it isn't.  It's really just when some call from inside the framework crashes.  So your own Dart code with classes not directly running inside the framework won't be catched  by that.  So after some digging on Stack Overflow we found this basically.  So you have to run the whole Flutter app.  As you know, everything on Flutter is a widget.  So also the whole app is run it's zoned basically and that wraps the whole widget basically  inside an error handling.  So we are now logging in from there and we saw some crash logs actually.  Damn it.  But okay.  Our error handler looks actually like this.  So when it's a release build we log it to Sentry.  But what's more interesting here is that also when it's a release build and it's not an  exception that comes from somewhere out of background processing, then we directly close  the app.  So in that case we know the crash happened somewhere in the foreground is highly possible,  highly possibly UI related and with that can create a state for the user that we don't  want to leave the user in.  Because Flutter on its own when it crashes it doesn't crash the app.  The app doesn't close.  Instead it shows something like this.  So that's really cool for debugging but you don't want to show that to the user of course.  So that's why, yeah, that's why we, when we see it's not a background error that does  something unpredictable with the UI we close the app.  Of course you want to keep that in debugging.  So that's why we came up with the solution because in debugging when you use hot reload  and you try out some code, put it on the device, you see this because it didn't run, you can  maybe directly see what was the problem, change the code directly, press hot reload  again and this will just go away and that will proceed where it was before.  Yeah, okay, the biggest thing I personally think is a blocker for Flutter itself is that  there is no background execution of Dart code yet.  So when there's no screen around, no activity, you cannot execute any Dart code.  It always needs a screen.  And with that when you for example get push notifications on Android it's quite common  that you get a push notification, you talk to your persistence or to your backend even,  get some data and then show the notification actually depending on the data of the user.  This way you can't do that.  You can do push notifications but just when they are completely defined by your backend.  With some simple actions that directly go into your app.  For example, custom actions on notifications are also not possible because you cannot execute  something in the background.  They are working on this but as a tip, keep your users data maybe on native side you want  to use the account manager anyway.  So more things are like CI, we're using traffic CI with fast line that works quite good out  of the box.  Of course on iOS it's a bit more complex with the signing there but it works quite good.  Then testing, Flutter supports unit tests, which are tests and which are tests are really  good because they are basically testing your UI like a unit test.  So you can unit test your UI because your UI is basically an immutable tree out of widgets  and you can just test what data is inside these immutable objects like a unit test.  But there is also integration test where you can run it on a real device and instrument  the UI.  Integration was the biggest problem we had actually because the tooling for localization  is a bit sad I would say because you have to write Dart code that defines your strings,  run this through a tool that will generate some template files.  You have to use this template files to create your own string files.  Take all the string files, run it through a tool again which generates Dart code and  you can put it into your app.  So no one wants to do that.  Especially when you are coming from Android for example where you just have the string  XMLs.  So we created our own system which is based on JSON and which just does some simple parsing  for Pluel or for placeholders.  We didn't open source that yet but there is some good medium article that describes exactly  that as well.  So someone else came up with it as well.  So as I'm short on time now, mobile apps with Flutter regarding non-native UI on Android  for example, material design is native, same on Flutter so you will be covered.  For iOS it's a bit more difficult because you have to then do some ifs inside your  UI code and maybe use a different widget that then looks like iOS.  They are also inside the Flutter framework but you have to invest a little bit coding  there.  Then about the feature and update gap, it's maintained by Google and even Flutter is the  first target now for the material design team so when the material design team at Google  comes up with something new, Flutter is the first target to implement it in now.  Then regarding system integrations for hardware integration for example, there are platform  channels and these are really easy to use.  They are basically like a JSON interface but it's really easy to set up.  It's directly integrated into the native side of your code that gets generated when you  create a new project so inside the Flutter activity where the whole app is running in  and there's also directly some APIs to use it on the Flutter side.  Then regarding bad performance, when you build for production it's compiled to native so  it can possibly even be faster than apps built against the Android SDK because apps against  the Android SDK are shipped in byte code and byte code always runs on a VM.  This is directly running on the machine.  Hot reload is really a game changer.  The Android team also tried to do that with Instant Run but I personally always turn it  off because you never know when it works and when not.  This thing just works.  It's really a game changer for when you are working with Flutter.  I would actually say it more looks like this then.  For Flutter you can build something that is not as complex to do anymore as pure native.  Of course when you want to be really sophisticated and integrated with the system features you  will have to go a bit extra but overall the result will be quite like the native application  I would say.  And that's how I personally felt after using Flutter and coming back to our native apps  that we are still maintaining.  So I really felt like what's going on here.  It's so damn slow.  It felt like working with my hands bound behind the back.  It was like what the heck is this really how I worked before?  So Flutter is really damn fast in development.  So you are really productive with it.  I actually wanted to do some live coding still but I guess time is out now.  So yeah, thanks a lot.  And yeah, I have to say this we are hiring as well.  So when you want to do Flutter approach me.  And yeah, otherwise thanks a lot.  I don't have my Android Studio here anymore.  Otherwise I would show some code actually.  Yes.  Are we good to go?  We have two microphones over there.  Thank you.  Thank you for your talk.  Do you have any kind of approach how we can integrate C++ libraries in Flutter projects  without maybe channels?  Yeah, so far there's no direct integration.  I just looked it up myself yesterday because I really like Object Box and Object Box is  directly doing C++.  So I looked how to do Object Box with Flutter but there's no way yet.  They don't have, of course it should be possible somehow but you have to dig really deep to  make that running.  So the only advice they give now is go platform channel and from the activity go C++.  But yeah, then I mean you do the bridging again across Java that doesn't make sense when  you go native.  But they're working on it.  More questions.  Seems not.  Okay.  Thank you.
_DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_0_1547.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_1548_1979.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_1980_2351.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_2352_4547.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_4548_5255.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_5256_10199.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_10200_16799.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_16800_17243.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_17244_17291.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_17292_17747.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_17748_18251.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_18252_18743.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_18744_19247.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_19248_19739.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_19740_20231.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_20232_21671.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_21672_22151.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_22152_22631.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_22632_23123.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_23124_23603.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_23604_24083.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_24084_24563.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_24564_25031.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_25032_25175.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_25176_25451.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_25452_28607.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_28608_30407.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_30408_31211.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_31212_33155.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_33156_40139.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_40140_41339.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_41340_42887.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_42888_46187.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_46188_47759.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_47760_50435.png _DCBerlin18_208_Friedrich_Production_Fluttering_DA_2RKbrKgHSI4_50436_50438.png