Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Droidcon SF 2017: Building Modern Cross Platform Apps with Flutter

vinaygaba
November 06, 2017

Droidcon SF 2017: Building Modern Cross Platform Apps with Flutter

Link to video - https://www.youtube.com/watch?v=GJyYv58eWOU

In this talk, you will learn about getting started with Flutter - a framework that helps you build modern 60 fps mobile apps for iOS and Android. Flutter uses Dart for its development but prior knowledge or use of Dart is not required to attend this talk. We will look at the various features Flutter provides including topics like building layouts with material design, debugging and more.

vinaygaba

November 06, 2017
Tweet

More Decks by vinaygaba

Other Decks in Technology

Transcript

  1. lutter
    Building Modern
    X - Platform Apps
    with
    Vinay Gaba
    @vinaygaba

    View Slide

  2. What is Flutter ?

    View Slide

  3. What is Flutter ?
    Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool

    View Slide

  4. What is Flutter ?
    Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool

    View Slide

  5. What is Flutter ?
    Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool

    View Slide

  6. What is Flutter ?
    Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool

    View Slide

  7. What is Flutter ?
    Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool

    View Slide

  8. View Slide

  9. What is Flutter ?
    Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool

    View Slide

  10. Open source SDK for building cross-platform apps by Google
    Support for Android & iOS
    Designed keeping both developers and designers in mind
    Allows building beautiful 60 FPS apps.
    Designed for speed and is an excellent prototyping tool
    What is Flutter ?

    View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. But how is it
    different ?

    View Slide

  15. But how is it
    different ?
    Uses neither WebView nor OEM widgets that’s shipped with a device
    SDK is shipped with the app
    Uses its own high-performance rendering engine to draw widgets
    Flutter implements most of its system in Dart

    View Slide

  16. Uses neither WebView nor OEM widgets that’s shipped with a device
    SDK is shipped with the app
    Uses its own high-performance rendering engine to draw widgets
    Flutter implements most of its system in Dart
    But how is it
    different ?

    View Slide

  17. Source: https://hackernoon.com/whats-revolutionary-about-flutter-946915b09514

    View Slide

  18. Source: https://hackernoon.com/whats-revolutionary-about-flutter-946915b09514

    View Slide

  19. Source: https://hackernoon.com/whats-revolutionary-about-flutter-946915b09514

    View Slide

  20. Uses neither WebView nor OEM widgets that’s shipped with a device
    SDK is shipped with the app
    Uses its own high-performance rendering engine to draw widgets
    Flutter implements most of its system in Dart
    But how is it
    different ?

    View Slide

  21. But how is it
    different ?
    Uses neither WebView nor OEM widgets that’s shipped with a device
    SDK is shipped with the app
    Uses its own high-performance rendering engine to draw widgets
    Flutter implements most of its system in Dart

    View Slide

  22. But how is it
    different ?
    Uses neither WebView nor OEM widgets that’s shipped with a device
    SDK is shipped with the app
    Uses its own high-performance rendering engine to draw widgets
    Flutter implements most of its system in Dart

    View Slide

  23. But how is it
    different ?
    Uses neither WebView nor OEM widgets that’s shipped with a device
    SDK is shipped with the app
    Uses its own high-performance rendering engine to draw widgets
    Flutter implements most of its system in Dart

    View Slide

  24. Flutter Widget
    Framework

    View Slide

  25. Flutter Widget
    Framework
    Inspired from React
    Building blocks of UI are widgets. Composition over inheritance
    Everything is a widget. Even the app is a widget
    Widgets in Flutter are immutable

    View Slide

  26. Flutter Widget
    Framework
    Inspired from React
    Building blocks of UI are widgets. Composition over inheritance
    Everything is a widget. Even the app is a widget
    Widgets in Flutter are immutable

    View Slide

  27. Flutter Widget
    Framework
    Inspired from React
    Building blocks of UI are widgets. Composition over inheritance
    Everything is a widget. Even the app is a widget
    Widgets in Flutter are immutable

    View Slide

  28. Flutter Widget
    Framework
    Inspired from React
    Building blocks of UI are widgets. Composition over inheritance
    Everything is a widget. Even the app is a widget
    Widgets in Flutter are immutable

    View Slide

  29. Flutter Widget
    Framework
    Inspired from React
    Building blocks of UI are widgets. Composition over inheritance
    Everything is a widget. Even the app is a widget
    Widgets in Flutter are immutable

    View Slide

  30. View Slide

  31. Hello World

    View Slide

  32. $ git clone -b alpha https://github.com/flutter/flutter.git
    $ export PATH=`pwd`/flutter/bin:$PATH

    View Slide

  33. $ flutter doctor

    View Slide

  34. $ flutter doctor

    View Slide

  35. $ flutter create myapp

    View Slide

  36. $ flutter create myapp

    View Slide

  37. View Slide

  38. View Slide

  39. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  40. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  41. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  42. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  43. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  44. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  45. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  46. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”,
    textDirection: TextDirection.ltr)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  47. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”,
    textDirection: TextDirection.ltr)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  48. void main() {
    runApp(
    new HelloWorldApp(
    textToDisplay: new Text("Hello World”,
    textDirection: TextDirection.ltr)
    )
    );
    }
    class HelloWorldApp extends StatelessWidget {
    HelloWorldApp({this.textToDisplay});
    final Text textToDisplay;
    @override
    Widget build(BuildContext context) {
    return new Center(
    child: textToDisplay,
    );
    }
    }

    View Slide

  49. Lets Prototype!

    View Slide

  50. View Slide

  51. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  52. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  53. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  54. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  55. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  56. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  57. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  58. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  59. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Container();
    }
    }

    View Slide

  60. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }

    View Slide

  61. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }

    View Slide

  62. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }

    View Slide

  63. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(),
    body: new Container(),
    );
    }
    }

    View Slide

  64. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(
    child: new Icon(Icons.add_comment, color: Colors.white),
    onPressed: null),
    body: new Container(),
    );
    }
    }
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(
    child: new Icon(Icons.add_comment, color: Colors.white),
    onPressed: null),
    body: new Container(),
    );
    }
    }

    View Slide

  65. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(
    child: new Icon(Icons.add_comment, color: Colors.white),
    onPressed: null),
    body: new Container(),
    );
    }
    }

    View Slide

  66. class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(
    leading: new Icon(Icons.menu),
    title: new Text("Inbox"),
    actions: [
    new IconButton(
    icon: new Icon(Icons.search, color: Colors.white),
    onPressed: null)
    ],
    ),
    floatingActionButton: new FloatingActionButton(
    child: new Icon(Icons.add_comment, color: Colors.white),
    onPressed: null),
    body: new Container(),
    );
    }
    }

    View Slide

  67. class Email {
    const Email(
    {this.sender,
    this.subject,
    this.emailBody,
    this.timeStamp});
    final String sender;
    final String subject;
    final String emailBody;
    final String timeStamp;
    }
    List _getInboxEmails() {
    return [
    new Email(
    sender: "[email protected]",
    subject: "Email Subject",
    emailBody: "Thanks for nothing!",
    timeStamp: "Oct 13"),
    new Email(...),
    .
    .
    ];
    }

    View Slide

  68. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red,
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  69. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(
    emails: _getInboxEmails()
    ),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red,
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }
    runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(
    emails: _getInboxEmails()
    ),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red,
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  70. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(
    emails: _getInboxEmails()
    ),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red,
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }
    class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  71. runApp(
    new MaterialApp(
    title: 'Gmail',
    home: new GmailInbox(
    emails: _getInboxEmails()
    ),
    theme: new ThemeData(
    primaryColor: Colors.red, accentColor: Colors.red,
    )
    )
    );
    class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  72. class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  73. class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  74. class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(...);
    }
    }

    View Slide

  75. class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(...),
    floatingActionButton: new FloatingActionButton(...),
    body: new Container())
    );
    }
    }

    View Slide

  76. class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(...),
    floatingActionButton: new FloatingActionButton(...),
    body: new ListView(
    padding: new EdgeInsets.symmetric(vertical: 8.0),
    children: emails.map((Email email) {
    return new GmailListItem(
    email: email
    );
    }).toList())
    );
    }
    }
    class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(...),
    floatingActionButton: new FloatingActionButton(...),
    body: new ListView(
    padding: new EdgeInsets.symmetric(vertical: 8.0),
    children: emails.map((Email email) {
    return new GmailListItem(
    email: email
    );
    }).toList())
    );
    }
    }

    View Slide

  77. class GmailInbox extends StatelessWidget {
    GmailInbox({this.emails});
    final List emails;
    @override
    Widget build(BuildContext context) {
    return new Scaffold(
    appBar: new AppBar(...),
    floatingActionButton: new FloatingActionButton(...),
    body: new ListView(
    padding: new EdgeInsets.symmetric(vertical: 8.0),
    children: emails.map((Email email) {
    return new GmailListItem(
    email: email
    );
    }).toList())
    );
    }
    }

    View Slide

  78. View Slide

  79. View Slide

  80. Row
    Widget Column
    Row Widget
    Widget
    Widget
    Widget

    View Slide

  81. class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }

    View Slide

  82. class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }

    View Slide

  83. class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }

    View Slide

  84. class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }

    View Slide

  85. class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }
    class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }

    View Slide

  86. class GmailListItem extends StatelessWidget {
    GmailListItem({Email email})
    : email = email,
    super(key: new ObjectKey(email));
    final Email email;
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }
    }

    View Slide

  87. @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }

    View Slide

  88. @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }

    View Slide

  89. @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(
    child: new CircleAvatar(
    child: new Text(email.sender[0].toUpperCase()),
    backgroundColor: _getRandomColor()),
    padding: new EdgeInsets.all(15.0),
    ),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }

    View Slide

  90. new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    @override
    Widget build(BuildContext context) {
    return new Row(
    children: [
    new Container(
    child: new CircleAvatar(
    child: new Text(email.sender[0].toUpperCase()),
    backgroundColor: _getRandomColor()),
    padding: new EdgeInsets.all(15.0),
    ),
    new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )
    ]
    );
    }

    View Slide

  91. new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )

    View Slide

  92. new Container(
    child: new Column(
    children: [
    new Row(),
    new Text(),
    new Text()
    ],
    ),
    )

    View Slide

  93. new Container(
    child: new Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    new Row(),
    new Text(email.subject,
    maxLines: 1,
    overflow: TextOverflow.ellipsis,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 14.0)),
    new Text(email.emailBody,
    maxLines: 1,
    overflow: TextOverflow.ellipsis,
    style: new TextStyle(color: Colors.grey, fontSize: 14.0))
    ],
    ),
    )

    View Slide

  94. new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0)),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )

    View Slide

  95. new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0)),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )

    View Slide

  96. new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0)),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )

    View Slide

  97. new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Expanded(
    child: new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0))
    ),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )
    new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Expanded(
    child: new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0))
    ),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )

    View Slide

  98. new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Expanded(
    child: new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0))
    ),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )

    View Slide

  99. new Container(
    child: new Column(
    ...
    children: [
    new Row(
    children: [
    new Expanded(
    child: new Text(email.sender,
    style: new TextStyle(
    color: Colors.black,
    fontWeight: FontWeight.bold,
    fontSize: 16.0))
    ),
    new Text(email.timeStamp,
    style: new TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: 12.0))
    ]
    ),
    new Text(...),
    new Text(...)
    ],
    ),
    )

    View Slide

  100. iPhone Android

    View Slide

  101. What Else ?

    View Slide

  102. What Else ?
    Unit, Integration & Widget Testing !
    Animations
    Accessing Platform Specific Features
    Great Tooling (Dart Analyzer, Render Tree Dumps, Perf Overlays)

    View Slide

  103. Thank you!
    Vinay Gaba
    @vinaygaba

    View Slide