1 of 62

Get Flapping with

2 of 62

Abraham Williams

Pearl Latteier

Senior Developers at Bendyworks

Google Developer Experts

Organizers of GDG Madison

​

3 of 62

slides.today

4 of 62

Cross Platform

Mobile Apps!

5 of 62

6 of 62

Ionic

React Native

NativeScript

Flutter

7 of 62

Ionic

​

​

8 of 62

Ionic

Write HTML/JS/CSS

​

9 of 62

Ionic

Write HTML/JS/CSS

Display in WebView

​

10 of 62

Ionic

Write HTML/JS/CSS

Display in WebView

Cordova or Capacitor wrapper

​

11 of 62

React Native

12 of 62

React Native

Write React

​

13 of 62

React Native

Write React

OEM Widgets

​

14 of 62

React Native

Write React

OEM Widgets

JS bridge connects to native APIs

15 of 62

NativeScript

16 of 62

NativeScript

Write JS, TypeScript, Angular, or Vue

​

17 of 62

NativeScript

Write JS, TypeScript, Angular, or Vue

OEM Widgets

18 of 62

NativeScript

Write JS, TypeScript, Angular, or Vue

OEM Widgets

Native APIs injected into JS VM

19 of 62

Flutter

20 of 62

Flutter

Write Dart

​

21 of 62

Flutter

Write Dart

Compiles to native code

22 of 62

Flutter

Write Dart

Compiles to native code

Flutter widgets

23 of 62

Dart

24 of 62

Static typing

Catch bugs early

25 of 62

Just-in-time

compilation

Hot-reloading for fast dev

26 of 62

Ahead-of-time

compilation

Fast, predictable native code

​

27 of 62

No templating language

All Dart, all the time

28 of 62

Skia

Graphics engine

29 of 62

Widgets and rendering live in your app

30 of 62

download size

vs. customizable UI

31 of 62

DEMO TIME

32 of 62

Widgets

33 of 62

Everything’s a widget!

34 of 62

Layout widgets

​

​

flutter.io/widgets

35 of 62

Style widgets

​

​

flutter.io/widgets

36 of 62

Animation widgets

​

​

flutter.io/widgets

37 of 62

Scaffold

AppBar

Text

Color

IconButton

Container

BoxDecoration

LinearGradient

Center

DogList

HomePage Widget

38 of 62

A Basic Widget

39 of 62

Stateless Widget

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {

return MaterialApp(

title: 'Good Dogs',

theme: ThemeData(brightness: Brightness.dark),

home: MyHomePage(title: 'Good Dogs'),

);

}

}

40 of 62

Stateless Widget

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {

return MaterialApp(

title: 'Good Dogs',

theme: ThemeData(brightness: Brightness.dark),

home: MyHomePage(title: 'Good Dogs'),

);

}

}

41 of 62

Stateless Widget

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {

return MaterialApp(

title: 'Good Dogs',

theme: ThemeData(brightness: Brightness.dark),

home: MyHomePage(title: 'Good Dogs'),

);

}

}

42 of 62

Stateless Widget

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {

return MaterialApp(

title: 'Good Dogs',

theme: ThemeData(brightness: Brightness.dark),

home: MyHomePage(title: 'Good Dogs'),

);

}

}

43 of 62

Stateless Widget

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {

return MaterialApp(

title: 'Good Dogs',

theme: ThemeData(brightness: Brightness.dark),

home: MyHomePage(title: 'Good Dogs'),

);

}

}

44 of 62

Stateless Widget

class MyApp extends StatelessWidget {

Widget build(BuildContext context) {

return MaterialApp(

title: 'Good Dogs',

theme: ThemeData(brightness: Brightness.dark),

home: MyHomePage(title: 'Good Dogs'),

);

}

}

45 of 62

A Stateful Widget

46 of 62

Stateful Widget

class MyHomePage extends StatefulWidget {

_MyHomePageState createState() => _MyHomePageState();

}

47 of 62

Stateful Widget

class _HomePageState extends State<HomePage> {

int counter = 0;

​

void increment() {

setState(() { this.counter++ });

}

​

Widget build(BuildContext context) {

return Button(child: Text('Click me'));

}

}

48 of 62

State is long-lived

49 of 62

Widgets get reborn

50 of 62

51 of 62

Animation

52 of 62

Built-in Animation

53 of 62

Custom Animation with Tween

Mikkel Ravn, “Zero to One with Flutter”, Medium

54 of 62

Testing

55 of 62

Built-In Testing Tools

import 'package:test/test.dart'

import 'package:flutter_test/flutter_test.dart'

import 'package:flutter_driver/driver_extension.dart'

​

56 of 62

Testing

testWidgets('Displays app bar', (WidgetTester tester) async {

MyHomePage homePage = MyHomePage(title: 'Test Dogs');

await tester.pumpWidget(MaterialApp(home: homePage));

​

Finder titleFinder = find.text('Test Dogs');

expect(titleFinder, findsOneWidget);

});

​

57 of 62

Testing

testWidgets('Displays app bar', (WidgetTester tester) async {

MyHomePage homePage = MyHomePage(title: 'Test Dogs');

await tester.pumpWidget(MaterialApp(home: homePage));

​

Finder titleFinder = find.text('Test Dogs');

expect(titleFinder, findsOneWidget);

});

​

58 of 62

Testing

testWidgets('Displays app bar', (WidgetTester tester) async {

MyHomePage homePage = MyHomePage(title: 'Test Dogs');

await tester.pumpWidget(MaterialApp(home: homePage));

​

Finder titleFinder = find.text('Test Dogs');

expect(titleFinder, findsOneWidget);

});

​

59 of 62

Resources

60 of 62

More Flutter at Mobile Era

Take off with Flutter

Jon Grythe Stødle

Thursday 1st November, 13:00 - 14:00

Lancing

​

Flutter in Action: How to build cross-platform app with Dart

Vitalii Bobrov

Thursday 1st November, 14:00 - 15:00

Lancing

​

61 of 62

We design and build software that stands the test of time, specializing in Ruby on Rails, JavaScript, Clojure, and Ionic.

​

Craft a project with us at bendyworks.com

62 of 62

Find today’s slides at slides.today

Pearl Latteier

pearl@bendyworks.com

twitter.com/pblatteier

github.com/pearlbea

Abraham Williams

abraham@bendyworks.com

twitter.com/abraham

github.com/abraham

​