Shalitha Suranga Programmer | Author of Neutralino.js and Jerverless

How to create desktop applications with Flutter

4 min read 1288

Introduction

There are several types of applications that developers can choose to write: console applications, mobile applications, web applications, and desktop applications.

Desktop applications run inside a system window with various UI elements. If you are going to make a desktop application, there are multiple different frameworks, UI-toolkits, and programming languages to choose from.

There are two types of desktop application development APIs: platform-specific and cross-platform. The platform-specific APIs only support one targeted operating system. For example, Cocoa API provides interfaces for developing desktop apps for the macOS platform. On the other hand, cross-platform APIs let developers make desktop applications for multiple operating systems with a single generic API.

Nowadays, cross-platform development frameworks are popular due to the following reasons:

  • Developers can maintain a single codebase for multiple platforms, because the cross-platform framework’s API provides a good abstraction for platform-specific APIs
  • Rapid feature delivery, meaning there is no need to implement the same feature for different operating systems by writing platform-specific code so new features can be delivered efficiently

In this article, I will explain how to create, build, and release native cross-platform desktop applications with Flutter. We are also going to discuss the reason behind Flutter’s popularity.

What is Flutter?

Flutter is a cross-platform application development framework that we can use to build natively compiled applications for multiple platforms: mobile, desktop, and web.

The known supported output targets are Android, iOS, HTML, HTML Canvas, Linux, Windows, macOS, and Fushia. Flutter uses Dart as the application development language.

Flutter currently focuses more on mobile application development, but supports desktop-based targets as well.

This framework comes with its own widgets toolkit. When a particular Flutter application is launched, Flutter will render the application’s UI controls via the Skia graphics library.

Why is Flutter so popular?

In the cross-platform framework development field, the most critical problem is how to place the abstraction layer for all platforms. In other words, how to offer a generic API for developers without creating performance issues for the application.

We made a custom demo for .
No really. Click here to check it out.

Desktop application development frameworks such as Electron introduced a web browser for rendering. Apache Cordova and Ionic mobile application development frameworks solved the problem in the same way. Even though those frameworks gave simple cross-platform APIs for developers, there are critical performance issues due to the web browser-based rendering.

Flutter offers simple, cross-platform APIs via Dart libraries while also maintaining superb performance.

Developing a desktop application with Flutter

In this tutorial, I will show how to make a simple cross-platform desktop application with Flutter.

Setting up Flutter development environment

Setting up Flutter is a piece of cake because it’s all about entering some terminal commands.

First, we need to install Flutter SDK with the following command:

$ sudo snap install flutter --classic

After that, we need to enable desktop development mode:

$ flutter config --enable-<platform>-desktop
// <platform> = linux, windows, macos

If the desktop mode is enabled, the flutter devices command should list down your current operating system.

Screenshot of Flutter devices command

Creating a new Flutter app

Like any other typical CLI, we can create a new application with the create command as shown below:

$ flutter create desktop-app

The above command will scaffold a simple starter project for us. The starter project contains minimal code with comments to help us understand how Flutter works.

The lib/main.dart file contains the main source code of your application. Let’s modify the main source code as shown below to create a simple “Hello World” application:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TextPad',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: Scaffold(
        body: Center(
          child: Text('Hello World')
        ),
      ),
    );
  }
}

You can view this project on Github here.

After editing the main source file, enter the following command to run your application:

$ flutter run -d <platform>
// <platform> = linux, windows, macos

The above command will open the Flutter “Hello World” app in a native window. The native window will be styled according to the current operating system and system theme configuration.

Screenshot of Flutter "Hello World" app on debug mode

Debugging the Flutter app

The Flutter development environment supports the hot reloading feature. Therefore, we can press r key in the console where you entered the flutter run command to trigger hot reloading. Try changing the text widget’s content while the application is running in debug mode.

Implementing a cross-platform desktop application

Let’s implement a small cross-platform desktop application with Flutter. We are going to make a small text editor application called “TextPad”. TextPad has a large, multi-line text field where we can type our notes. It also has an action button to save the current note to a file. A screenshot of TextPad is shown below.

Screenshot of sample textpad app

As mentioned, the save button on the top right will write the current note into a text file. After saving the file, TextPad will display a notification message about the task’s completion.

Screenshot of textpad in use

Similar to the previous Hello-World application, add the following source code into the main application source file:

import 'dart:io';
import 'package:flutter/material.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

    final textController = new TextEditingController();
    final globalKey = GlobalKey<ScaffoldState>();
    final String fileName = 'textPadNote.txt';

     Future<void> _exportToFile(BuildContext context) async {
       final File file = File('${Directory.current.absolute.path}/${fileName}');
       final snackBar = SnackBar(content: Text('Saved to: ${file.path}'));

       await file.writeAsString(textController.text);
       globalKey.currentState.showSnackBar(snackBar);
    }
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      title: 'TextPad',
      theme: ThemeData(
                brightness: Brightness.dark,
           ),
      home: Scaffold(
        key: globalKey,
        appBar: AppBar(
          title: Text('TextPad'),
          actions: <Widget>[
              IconButton(
                    icon: const Icon(Icons.save),
                    tooltip: 'Export to ${fileName}',
                    onPressed: () {_exportToFile(context);}
                  )]
        ),
        body: Center(
          child: TextField(
                controller: textController,
                maxLines: null,
                keyboardType: TextInputType.multiline,
                expands: true,
                  decoration: InputDecoration(
    hintText: 'Play with your notes here...',
    contentPadding: EdgeInsets.all(12.0)
  ),
          ),
        ),
      ),
    );
  }
}

View this project on Github here.

Building your Flutter desktop application with portable binaries

Before releasing your application to the internet, you can build Flutter applications to obtain portable binaries. These binaries also can be shared with users or testers. Moreover, you can make installable binaries with your favorite installer tools.

When we are debugging the application, debuggable binaries will be created. However, debuggable binaries are not optimized for a release. Execute the following command on the terminal to make optimized binaries:

$ flutter build <platform>
// <platform> = linux, windows, macos 

How to release your application

There are different ways to release your Flutter applications, but the deployment method depends on the type of operating system. For example, If you are going to release your application for Linux users, you can deploy your Flutter application to the Snapcraft software store. If you need to deploy your application for Windows users, you can make a Windows Installer Package (MSI) or a new Windows app package (MSIX) with the help of a third-party tool.

However, the Flutter team still doesn’t recommend releasing Flutter applications for production use because the Flutter Desktop framework is still not stable. Very soon, we can expect further support for deploying application packages from the Flutter team.

Conclusion

Nowadays, Electron is very popular for desktop application development because it allows developers to make desktop apps with web technologies. However, Electron applications often become bloatware due to high physical resource usage. Flutter is performing better than Electron because it doesn’t perform the application’s GUI logic on a web browser.

Flutter does have some pain points for developers. It comes with an unfamiliar programming language and a brand new widgets toolkit. Still, release binaries for desktop platforms are not lightweight.

Flutter’s initial stage impressed everyone with overall impressive performance and features. I believe Flutter desktop will compete with Electron soon!

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Shalitha Suranga Programmer | Author of Neutralino.js and Jerverless

2 Replies to “How to create desktop applications with Flutter”

  1. It was very helpful, i am working on android side of flutter…to know this kind of information it helps me alot in motivation to learn more about flutter…

Leave a Reply