> This fundamentally does not work for anyone with more than 10M+ installs just like you can't write Mandarin and English in one script.
Well, I did work on a Flutter app with a tiny team between 2018-2021 and we had 15M installs, were app of the day, got featured multiple times in the App Store, got Google’s design award, were a preloaded app on iPhones in Apple Stores in several countries, and were overall doing quite well.
It was a very focused app though, so the size of our codebase didn’t really grow with the number of installs.
New iOS and Android features, sometimes backward-incompatible are introduced.
And now, you need your dependencies to implement them. Which might or might not happen. At best, this makes usage inferior. At worst, you can no longer publish an update in app stores.
This app was started in 2017 and it is still running today and making (way more modest than back then) revenue. It’s just that I don’t work on it anymore.
I only have one meeting a month nowadays so I might take a look if that situation ever changes (hopefully it doesn't!).
Regardless, congrats on the launch.
> the macOS app and Chrome extension communicate via WebSockets on localhost; nothing leaves your machine.
So the macOS app sets up a local webserver on some port that the Chrome extensions knows about in advance? Smart, kinda like how I had to do an auth flow for one of my CLI apps.
> I only have one meeting a month nowadays so I might take a look if that situation ever changes (hopefully it doesn't!).
I'm happy for you
> So the macOS app sets up a local webserver on some port that the Chrome extensions knows about in advance? Smart, kinda like how I had to do an auth flow for one of my CLI apps.
Exactly like this! Some caveats there since Chrome actually shuts down extensions after 30 seconds or so if nothing happens (so you need to keep firing off messages across the connection to keep the extension alive).
I actually don't have any experience in that, but I think that you can absolutely do it. From what I understand, the IDEs just call the Flutter CLI and Dart analysis server, among other tools to get stuff done. From the top of my head, "flutter run", "flutter test", "flutter analyze", "flutter packages get" would be the commands you'd be using the most and could survive without using any IDEs. Of course you'd lose the autocompletion along with other IDE niceties, but I really believe that could be done. One thing is you might have to open XCode once to do the provisioning profile setup, but after that you should be good.
I'm hoping someone with more experience could chime in.
Thanks. Is having XCode necessary in order to build and publish for iOS (I guess yes)? I don't use apple computers and use linux, so if that's the case I'd need to buy a Mac and XCode to do so, no?
For iOS apps, you need a Mac. Maybe (and this is theoretical) you could set up a combined Fastlane & CI integration that builds the apps using some cloud service, such as Macincloud, Bitrise, etc. Fastlane would then build and upload the iOS test builds automatically so can use them on your phone using the internal testing group in TestFlight. When everything seems fine, then you can just promote the internal test build to production. Since Flutter custom renders everything, you could do most of the development on a Linux machine and test on Android emulator/device.
WRT cloud building: yes, it'd be more ideal to have a Mac especially if you want any platform specific UX or features but you can definitely get around it using just a Linux machine, an iOS device and some CI system.
You can also get around it using just a Linux and an Android device. You can press 'o' after you flutter run to change the platform on the fly to get iOS scroll physics, page transitions etc etc. But again, testing on the devices your users will be using is more ideal.
Thanks, glad you find it useful! And that's exactly the reason I open sourced it - I thought there was a need for a quite comprehensive but still simple sample app for people to learn :)
For the difference in coding time, it's hard to estimate. I'd say once you get the hang of it, which for me was quite fast, it's much more pleasant and generally faster than working with native Android. Hard UI related things on Android (rounded corners or customizing the design library components) are pleasant to do and make a lot of sense in Flutter.
Flutter and Dart come with a nice HTTP library out of the box. In my experience, it does everything you'd expect from a networking library. If you're looking for something like Retrofit on Android, there's a package called "jaguar_http" that does the job.
For taking/picking images, you'd use the officially supported "image_picker" plugin. It exposes a nice API based on Dart's Futures and handles Android's onActivityResult dance for you in the background. If you're looking into embedding a camera preview in a Flutter app, there's a package called "camera" for that.
There's generally a plugin that handles the platform stuff you need to do. If not, you can always create one and use Java/Kotlin/Swift/ObjC code to call the native SDK APIs you need yourself. Having published a couple plugins myself, I've found the plugin system to be really nice.
Like I said before in another comment, there's only so much I can fit in a Hacker News title. :) I'd like to think that a lot of people use the term "a cross-platform app" to mean "an app that works on Android and iOS" though. Or "an app that works on more than one platform using shared code".
I've been using Flutter for a year now, and I've loved it since the first time I gave it a try.
In my work, I've been using other cross-platform technologies, such as Xamarin and React Native briefly (actually currently doing a customer project with RN). In my experience, RN is not that bad and mostly gets the job done, but I've grown to like Flutter more. The tooling and documentation are top-notch ("it just works"), and since it custom renders everything, the UIs are consistent across devices and platforms. For example, with React Native I had to recently fight with a third-party library to have gradients (RN doesn't support them), but couldn't get the library working.
Another thing that I heard from colleagues was that React Native can introduce a lot of breaking changes between versions. I have a one-year-old hobby Flutter project and I was still able to run that without any pain when the first beta came out.
Being a native Android & Java guy for the last 5 years or so, having the strong type system of Dart also felt more natural to me than Javascript.
I've been starting work with Flutter over the past couple weeks. The tooling and general experience so far has been pretty nice, though it doesn't always "just work". The fact that flutter is so coupled to Cocoapods is a disappointment and it means your build system is dependent on Cocoapods not screwing up - quite a tall order. I already ran into an issue that required me to generate a new project, copy my source over to get a working app again, then inspect the source trees to see what went wrong. It turned out to be a Cocoapod symlink issue or something to that effect. Not entirely a Flutter issue but something to be wary of.
Some good points of Flutter so far:
* Hot reloading is fast, much easier to iterate on designs and experiments
* Plugins seem to be easy to make, they made an architecture that focuses on minimal boilerplate
* Being able to use async-await syntax on a whole UI view is a cool idea (like Android's onActivityResult() with much less typing involved). Push a view onto the navigation stack, let it collect input from the user, pop off the stack with a data structure representing the user input)
* Animations are easy
* Minimal opening of Xcode. Most days I can get by without ever opening it.
* Data flow architectures like the Elm Architecture or Redux are well supported
Some not-so-good points:
* Having null
* Material design is pushed way too hard - Cupertino widget documentation/examples are lacking
* Code generation needed for JSON parsing
* State for StatefulWidgets are generic over the Widget and not the other way around - I would have expected a StatefulWidget to be generic over a State e.g. `MyHomePage extends StatefulWidget<MyHomePageState>`
* Because of the previous point, the UI building function, build(), is usually on the State class and not the Widget class
* My relatively barebones app is around 33MB on iOS
Overall though I like it! Lots of good ideas and tooling. I one day want to create something with a similar architecture using a language like Rust instead of Dart, and native UI components instead of reimplementing the entirety of Android and iOS component behavior.
I don't really agree about pushing hard on Material Design. Sure, the current widget situation might be skewed towards Material components and Cupertino is lacking. For Material widgets, they've implemented almost everything, even the most obscure ones. But I think they're pushing more for customized UIs. Meaning, UIs that don't look Material or Cupertino, but are more of a branded experience, think Spotify, Tinder, Snapchat, etc. Designs that don't really conform to Material or iOS design languages. The Hamilton app is a good example of this. Sadly, I'm not a UI designer so I went with Material Design on this inKino app since that's an easy route for me.
With your other points, I generally agree. Didn't mean to imply that it "just works" 100% of the time. But compared to other cross-platform dev tools / SDKs I've used, I feel like Flutter does such a great job in the tooling department.
I must have been spoiled by Flow, Typescript, Kotlin, and Rust, because this (having null implicitly be a member of every type rather than a separate type) has been the major factor in my decision to avoid playing with Dart yet. It's so nice to not have to often manually re-check functions I'm editing to see whether or not each of the parameters are supposed to handle null, and to not have to document that in comments (the same way you usually end up documenting types in a dynamically typed language; this is what I'm using a typed language to get away from!).
I've been using React Native too and my experience is: I accomplish a lof of stuff in a few days, then lose a whole day trying to hack a custom Picker element or similar. Grrr.
Disclaimer: It's been over a year and Xamarin could've improved a lot during that time.
Coming from a Java/Kotlin background, I found C# to be really nice, but I had some issues with Xamarin tooling. I used Xamarin Studio and for the most part, it worked fine. Sometimes, there were some random crashes and project build errors that mysteriously resolved themselves. I also needed pie charts per the customer requirements and the best pie charting library I could find had licensing issues, so ended up implementing the pie chart myself which wasn't that bad.
To compare, I would say the Flutter tooling is really good, compared to Xamarin where sometimes I would not be confident with the tools. Also, with Flutter, I can share the UI layer entirely, compared to the Xamarin project where we only shared some plain business logic with written purely with C# without Android/iOS SDK dependencies. I know about Xamarin.Forms, but have no experience to compare it with Flutter. At the time the project team didn't want to use Forms, but I don't remember why.
There's only so much I could fit in the title, and I honestly didn't mean to mislead anyone. I can definitely see how it could be a little misleading now that you mentioned it.
Yeah I definitely thought this was sth. about making videos on mobile, but I don't think the title is purposefully trying to mislead anybody. Maybe titles should be allowed to have ~100-120 chars instead of 80, it's a bit too limiting.
As a native mobile developer of several years, I've always been somewhat skeptical of the various cross-platform solutions that have emerged over the years.
The WebView-based solutions weren't fast enough and sometimes behaved differently across devices because of different WebView versions. With React Native, the impression was far better because the performance actually can be quite good. But it's still hard to abstract the UI layer away when even the native Views on Android behave differently across devices and Android versions. I had to use almost a half of a day for fixing invisible drop-down menu items on some specific Samsung device on Android 4.1.2. Not to mention when you have to abstract the UI for both Android & iOS, which brings its own set of problems. It's one of the reasons why such a fundamental thing as navigation has been so hard to get right.
I feel Flutter is the first cross-platform SDK that gets something fundamentally right. Since every pixel on the UI is rendered by the framework, we as developers have better control of everything. It's going to have much better performance because there are no bridges between native and cross-platform land. Additionally, Samsung can't fuck up our UIs: once the UI works, it works the same on every device.
As a bonus, they also keep tremendous care of their codebase and they have the best documentation I've ever seen. My really simple, quick 4-line fix didn't go through until I wrote 30 lines of automated tests to go with it. After all, Flutter is going to be the native SDK for developing apps for Fuchsia, and I think Google has learned not to repeat the same mistakes that happened with Android again.
"Since every pixel on the UI is rendered by the framework"
This is a deal breaker for me. It's not about the ui feeling a bit off - the drawer going over instead of pushing things or some such, it's about losing the integration with the native OS.
For example the android version of the gallery app shown elsewhere doesn't adjust to font size changes (which can be done at the system level), won't make a sound when clicking things if sound on tap is set, has no accessibility support.
Rather then marking the entire word double tapping on a word in an input-text does nothing, long pressing on the input opens a non-native menu with cut/paste/copy while a regular input has share and translate (at least for me).
And this is just a minute of tests, it probably fails to integrate into the larger ecosystem in a gazillion ways - many of them you'll find out when users complain about it once you go into production.
This was tried before (for instance Java's swing vs SWT) it almost always results in eventually outdated slow interfaces that are a pain to migrate to newer technologies.
Thanks for the feedback! We are working on improving our accessibility now, which is required for our business-critical Google users and others. For example, you can follow this issue if you're interested: https://github.com/flutter/flutter/issues/12311
The clicking sound on button presses has been fixed in the latest build, and the Flutter team is working on accessibility. But I agree that a Flutter app will always have some deficiencies compared to a native app.
However, the question is whether a Flutter app will be Good Enough when the alternative is writing two separate apps. I would argue that even in the current alpha stage it's getting pretty close to Good Enough - the Hamilton app was written in Flutter and gets 4.7 stars on Google Play [1] so users aren't too bothered that double-tap doesn't select text.
Java Swing was slow, bloated and looked far less like a native app than Flutter. And in 2003 Windows had a 95% market share, so there was no major benefit to writing a cross-platform desktop application. Things may be different this time.
> However, the question is whether a .. [Flutter, Cordova, React-native etc app] .. will be Good Enough when the alternative is writing two separate apps
This is a more important consideration than is often given credit for, perhaps because the perspective we most often read about is the high end of the industry. But vast amounts of software is written to extremely tight budgets, often for small businesses, where there is flat-out zero chance of two native apps being written. It's choose-your-platform, or something cross-platform.
For very many of these kinds of apps, which are pretty much invisible from the blogs/HN/medium world, RN/Flutter/Cordova etc are perfectly appropriate. The fact that these may not be the best platforms from which to use the very latest, most hardware-entwined OS features, or to do highly custom 'delightful' bits of UX, is often in this world quite irrelevant.
I don't like the approach either, and the point about accessibility is an important one that's very much non-trivial (but developers often ignore it completely at first).
It's like making a web page that renders everything inside Canvas elements. If that doesn't seem like a good idea to you -- why would you build your mobile apps that way?
The interesting part of Flutter for me is that it powers Fuchsia.
IF Fuchsia becomes a major thing, like the future of Android (and I can't emphasise enough how much it is uncertain right now) then it might become very interesting as a way to publish your new app on Fuchsia while being able to publish it on Android as well in order to support `legacy` devices (again, supposing that Android is abandoned in favor of Fuchsia)
Otherwise, it is 'just' another hybrid solution with the usual caveats.
I also use a cross-platform framework that "renders every pixel". The two major problems I had are the lack of native input and the integration with native ad SDKs. I solved the input with overlaying a native input view on top of everything but it's very clunky and have to be careful to keep it the topmost in the view hierarchy. I haven't found a solution for native ads.
Most of the other things are relatively easy to solve if they come up as actual problem.
In fairness Qt also gets this right: It renders every pixel and it has a fast rendering architecture. Having used Qt, flutter is very attractive to me for the case where you have to work with a team. It can be hard to get together enough people nowadays who will want to work with even a little C++. The Qt libraries make it very easy IMO (most stuff is ref counted) but not everyone is going to buy that.
Qt is one of those things that I've heard of before, but did not know was still used for mobile development today.
The monthly commercial license fee is a bit of a downer though. I feel that a lot of software development agencies (my workplace included) are just not gonna bother with it and just use something free instead.
I agree about the C++ point with you. I have to confess I'm also one of those people who generally want to do things on a higher level. Would definitely give Qt a try if it was free for commercial purposes though.
The free license for Qt is the LGPL, which, although more restrictive than a fully permissive license like BSD or MIT, is still suitable for many commercial applications. (You can't ship proprietary modifications to Qt, but you can ship a proprietary app that includes Qt as a dependency. Your app can use a modified version of Qt if you open source your modifications.)
It's native in the sense that it doesn't bundle an entire Chrome browser runtime with it. But it does not interact with native APIs; it re-implements the native platform's look and feel.
You're applying the word "native" to the wrong thing.
"Native" in the context of GUI frameworks doesn't have to do with code being interpreted vs compiled. It means the framework creates UI using the toolkit that ships with the OS you're targeting. It means Cocoa on MacOS and UWP or WPF or WinForms on Windows.
It means when you scroll past the end of the text in a textbox you get a bouncy effect on macOS just like every other Mac application, because it's ultimately calling the same function that every other Mac application calls.
If someone made a JavaScript library that wrapped Cocoa and UWP, it would be called a "native" toolkit, because it wraps the controls that are shipped with each OS. That's why React Native is called what it is - it's actually creating dialogs and views on iOS with the same functions you would call if you were doing it in Swift.
There are pros and cons. One of my big concerns around something like Flutter is accessibility.
When you render everything on your own you lose the ability to hook into system-level frameworks for accessible content discovery. Their FAQ mentions it briefly but looking at the API support seems pretty sparse.
We're working on accessibility right now, it's incredibly important to us and our users. A big driver here is Google's usage of Flutter. There are business-critical teams at Google right now using Flutter, and they can't launch until a11y is finished. So we're working to finish and ship it. Stay tuned!
At least on Android, it turned out that if you claim that specific portion of the screen is, for example, android.widget.ScrollView, the system believes it. This can be verified with the HierarchyViewer. Some people in Flutter's Gitter group were confused because of this, since they thought Flutter doesn't draw its own widgets. While in fact it was the early accessibility implementation.
Well, I did work on a Flutter app with a tiny team between 2018-2021 and we had 15M installs, were app of the day, got featured multiple times in the App Store, got Google’s design award, were a preloaded app on iPhones in Apple Stores in several countries, and were overall doing quite well.
It was a very focused app though, so the size of our codebase didn’t really grow with the number of installs.