Flutter mobile, web and desktop — The stars race

In this article, we’ll explore the real capacity of Flutter in compiling to different platforms, mobile, web and desktop with the same source code.

This post was originally posted on blog.juliobitencourt.com.

The App

The famous GitHub stars ⭐️ on open-source projects are considered by many people a popularity meter, and although a project having more stars than others doesn’t mean anything, at least it shows that the community is enjoying and supporting the technology.

So through a simple application, we’ll measure the stars run of the main technologies capable to build mobile multi-platform apps. The layout has nothing extraordinarily different from what a normal Flutter app doesn’t have. That’s why I won’t explain how does the source code or resources work (only some key points).

The app contains:

  • Slivers
  • Flare animation
  • HTTP requests
  • Json parsing with json_serializable
  • Simple adaptable layout
  • Hyperlinks (external urls)

The image below shows the final result, and you can access the app on GitHubPages at jhbitencourt.github.io/stars-race to give it a look. Now let’s explore the different platforms.

Mobile

Everybody is already used to how to create a mobile Flutter project, and independent of the channel you are in, the resources will work fine on both Android and iOS.

The idea is based on making requests to the GitHub API to gather information about the open-source projects, and their stargazers count. The repositories I’m using are listed below, feel free to send a PR and add a different mobile tech.

You can try accessing https://api.github.com/repos/flutter/flutter for example. The API will bring lots of data about the project, but I’ll use only a few, as like RepoInfo below:

The package json_serializable is used to parse the json result. And the app state is managed with bloc and rxdart. So, based on the current stream state, we can show a loading, an error message, or the result data.

For the loading, we can show a stars animation built with Flare and available here.

And in case of any error, this is the message shown:

This is because the GitHub API has a limit of 60 requests per hour to a single IP, so the limit can be reached. More about this. Some places of the app can have a hyperlink to an external page, this is a common task and easily done on mobile (Android and iOS) with the help of url_launcher, from the Google team.

With all setup, we can run to mobile (smartphone and tablet) and it will work as expected:

  • flutter run
App running on smartphone
App running on tablet

Web

Flutter for the web, also known as Hummingbird, is currently in tech preview (not even in alpha), so definitely you must not use it in production. But nothing can hold us from testing it and being amazed.

Initially, the web part was separated on a different project flutter_web, which needed a more complex setup, besides problems with conflicts of package naming. But since September 10, all the source code was unified into the original SDK, and available in the master channel, once it is not stable.

So to use it, you must be at the master channel, and preferably updated with the last release.

  • flutter channel master && upgrade

After updating, flutter config --enable-web will enable the web configuration. After that, to enable flutter web on a created project you can just go to the folder and run flutter create ..

This will create a web folder with a file index.html, responsible to link the main.dart with the final js code.

Now when running flutter devices two new devices are listed:

The device web-server will create a local server, configured to a given port by Flutter, this same port can be accessed by any browser to try the app.

  • flutter run -d web-server

On the other hand, the chrome device will obviously run on Chrome an open a bridge to allow debugging the app.

  • flutter run -d chrome

This is enough to see the same app running on web! Even the initial Flare animation worked out-of-the-box (although some animations may not work properly). Definitely, many things still have a mobile-like look and feel, and there is much work to be done. An example is the mouse pointer, that when hovers a clickable object, is expected to change its visual.

Currently, we don’t have this kind of behavior out-of-the-box, and to do so is necessary a kind of a hack. For that, inside index.html we can define an id to the body of the page:

Now it is possible to reference the body inside a widget called HoverAware:

The Listener already provides many callbacks to mouse actions, notice that onPointHover and onPointerExit are listed as deprecated, which will change in the future, see the issue. Now when using this custom widget and hovering the specific areas, our cursor type will change through the body element reference.

This works perfectly when compiling to the web, but it will break our mobile code since when compiling to mobile we’re not allowed to use the package dart:html. The current solution is to use the package universal_html, which works as an embed of the real dart:html.

Now we create another widget called InkWellPlatformAware that extends from InkWell and inserts HoverAware in case we’re running on web, validated through the kIsWeb constant.

By using it, we have the expected behavior:

When clicking though, the external link won’t be opened, because the url_launcher plugin doesn’t work for the web. And for our feature to work, is necessary make use of universal_html again:

Now everything is perfectly ready to run on the web:

GitHub Pages

The GitHub Pages is a good option to host our flutter web page. And for that, we first need to build for the web:

  • flutter build web

The generated files are in <project_folder>\build\web:

I already have the repo jhbitencourt.github.io at GitHub and the idea is for the app to run at jhbitencourt.github.io/stars-race. You can learn more about GHPages here.

So all we need is to create a folder called /stars-race inside this repo and put all the generated files there, like this. And that’s it , go ahead and access jhbitencourt.github.io/stars-race, so easy, isn’t it?

Desktop

The mission now is to run the same app on Desktop. And if flutter web is in tech preview, the desktop embed is even more immature by the time I’m writing this. The most part of the source code are still being kept in a separate repository called flutter-desktop-embedding.

To integrate it with our project is also necessary to be on the last release of the master channel. The steps I’ll follow bellow are valid to windows as example, but can easily be adapted to linux/mac, to more information you can see at the readme from the original repo or the desktop page.

To avoid any troubles, run the prompt from windows on admin mode. And once in the master, is also possible to enable the desktop config running flutter config --enable-windows-desktop. Now with flutter doctor -v it will show up some warnings asking for the installation of Visual Studio and some of its components, to be able to compile apps for windows with C++.

It is necessary to download it from the website and install what is solicited by the flutter doctor. Notice, Visual Studio != VS Code.

With everything installed, the warnings from flutter doctor should be gone. Maybe it is necessary to restart the computer for it to take effect. Now we need to clone the repo flutter-desktop-embedding into our local files because we’ll need to copy come scripts and runners from the platform.

At the directory \flutter-desktop-embedding\example\windows, copy the folders resources and scripts along with all the files. Pasting them on our project, it should look like here.

For the app to run, it is needed to define the TargetPlatform before calling the function runApp(), this is because currently the desktop platform is not automatically recognized, and with the TargetPlatform null, errors will occur.

Here there is a detail for the app to continue running on 3 different platforms. The flutter desktop documentation says to define the TargetPlatform according to the following method:

However, flutter web doesn’t have access to dart:io, just like the mobile doesn’t access dart:html. And as Platform is defined in dart:io, the above code breaks the web version. That’s why the first code is more appropriate to ensure the app running on all platforms. With that is possible to run the app, flutter devices will list windows as a device.

So, flutter run -d windows results on the app magically running, how amazing is it?

Even the Flare animation, the API calls, the Json parsing, none of that were necessary to change. But there is only one last detail. The hyperlinks aren’t working, because when in desktop we can’t launch a link through universal_html or the default url_launcher.

Currently, the plugins support on desktop are not well defined as how they will be treated, because of that the existing plugins are not published at pub.dev. But are published at flutter-desktop-embedding/plugins. These plugins are on early-stage and probably will be integrated into the current ones, or changed places.

To open an url we’ll use the url_launcher_fde, an embed to the original one url_launcher, see more. So it can be added on pubspec:

You can read more about desktop plugins here. But this isn’t enough, we still need to add the plugin manually at the Runner from windows.

For that we open the file /windows/Runner.sln with Visual Studio. In File > Add > Existing project.. add the file .vcxproj from the plugin. The file is downloaded to the local directory at <flutter_home>.pub-cache\\git\\flutter-desktop-embedding-..\\plugins\\flutter_plugins\\url_launcher_fde.

Now at Project > Project dependencies.. it is necessary to define the project Runner as dependent on url_launcher_fde, and the project url_launcher_fde dependent on Flutter Build. The compilation order must be like this:

Now the file can be saved and Visual Studio closed. The plugin will be correctly configurated and when running the project again the external urls will be working. o/

Final considerations:

  • Should I use flutter web or desktop in a production environment? Not yet.
  • Should I use flutter web or desktop? Definitely yeah!

Of course, we needed to do some boring setup, mostly to the desktop part. But with this simple application is possible to feel a little taste of what the real flutter multiplatform is capable of.

And after all, you can answer in the comments, how long do you think it will take for flutter to get the first position on this run? :D

The source code is available on GitHub, access it and drop a ⭐️ if you enjoyed ;)

Flutter Community

Articles and Stories from the Flutter Community

Julio Henrique Bitencourt

Written by

juliobitencourt.com

Flutter Community

Articles and Stories from the Flutter Community

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade