2017-02-18

Dart for Java developers: Mobile apps with Flutter

In a previous installment of my series of posts about Dart for Java developers we took a brief look at how to write a simple web application using Dart. This time, I would like to introduce you to the Dart way of going mobile. It's called Flutter. Flutter had its first public appearance in 2015. At that time it was called Sky. Since then Flutter has evolved quite a bit. Although still being a technical preview it is possible to write real world applications. As with all prerelease solutions, some things will likely change. On the other hand, being an early adopter also means building up skills early.

The underlying idea of Flutter is to build Material Design mobile apps for Android and iOS with one code base using Dart as the programming language. On both platforms the user interface is not made of native components. Flutter handles all painting by itself. Nonetheless Flutter tries to provide expected behavior, for example by using appropriate gestures, animations and transitions. This approach has both pros and cons. I am not going to discuss them here, but leave pondering up to you.

At this point, you are probably asking yourslef how a Flutter application looks both in source code and up and running. I have created a Flutter version of the temperature conversion app. You can find it on GitHub. Here is a screenshot of the app running in the iOS Simulator:

Screenshot of the temperature conversion app

Before taking a look at the code, I would like to talk about system requirements. Currently you need a macOS or Linux machine. Support for Windows appears to be work in progress. Setting things up currently requires quite a few steps, but these are well documented. Finally, let’s take a look at the code. The basic structure of a Flutter app looks like this:

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

...

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: _appName,
      home: new MyHomePage(title: _appName),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
 
final String title;
 
@override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ..

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(config.title),
      ),
      body: new Block(
      ...
      )
    );
  }
 
...
}

The top-level function main() is the entry point of the application. We instantiate a class that extends StatelessWidget. As the name implies, such widgets have no mutable state. Its build()-method returns yet another widget: MaterialApp. It has a title and a home. The latter one is a StatefulWidget. It overrides createState(), which to no surprise returns a freshly created State. Its build()-method returns a Widget that represents the current state. This may look complicated at first sight, but in fact its super simple. Changes to the state result in build() being called. As you can see in my sample app at GitHub, there is a corresponding setSate() to set this chain in motion.

No comments:

Post a Comment