Flutter or React Native, a cross-platform dilemma | .droidcon Greece

Flutter or React Native, a cross-platform dilemma | .droidcon Greece

Nowadays the hype around Flutter is raising a lot. But what about the “(not so) old-fashioned” React Native?
In this talk, we will see the basics and the differences between the two frameworks. In particular, we will understand how to build User Interfaces and how the internals of the two framework works. Finally, we will try to understand when and why to choose a cross-platform framework and which of the two.
All this journey is based on the true story of an Android Developer that he wanted to explore the cross-platform jungle both for work and fun reasons.

9da5d5cc4b6a9f28058152e28364b02a?s=128

Marco Gomiero

September 24, 2019
Tweet

Transcript

  1. Flutter or React Native a cross-platform dilemma Marco Gomiero

  2. WHO I AM Mobile & Data Engineer @ Uniwhere MARCO

    GOMIERO COMPUTER ENGINEER Co-Leader @ GDG Venezia
  3. LET’S GET IN TOUCH! twitter.com/marcoGomier MARCO GOMIERO COMPUTER ENGINEER github.com/prof18

    marco.gomiero.93[at]gmail[dot]com marcogomiero.com
  4. Disclaimer

  5. Background

  6. Background Flutter React Native

  7. Agenda • History • Language • UI • Under the

    hood • Example • Conclusions
  8. History JANUARY 2015 First public preview MAY 2015 Open sourced

    and launched officially SUMMER 2013 First version developed during an internal hackathon 2013 2015 2015 React Native
  9. History JANUARY 2015 First public preview MAY 2015 Open sourced

    and launched officially SUMMER 2013 First version developed during an internal hackathon 2013 2015 2015 Flutter React Native MAY 2017 Alpha Release DECEMBER 2018 First 1.0 version APRIL 2015 Unveiled at Dart Dev Summit 2015 2018 2017
  10. Trends React Native Flutter UPDATE Last update: September 2019

  11. Trends Last update: September 2019

  12. LANGUAGE

  13. React Native • Javascript • ☠ for Object Oriented Devs:

    • Type Conversion • Sometimes silently fails • Prototype based inheritance • Ecosystem Confusion
  14. None
  15. Flutter • Dart, invented by Google in 2011 • Object

    Oriented friendly • e.g strongly typed but type can be inferred • Flat learning curve for OO devs • Mobile -> compiles to ARM and x86 code • Web -> transpiles to Javascript
  16. !crusade It’s not a language crusade, just my experience

  17. UI

  18. None
  19. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });
  20. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }
  21. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }
  22. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });
  23. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });
  24. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });
  25. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } });
  26. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); Components • Basic UI building blocks • Fit together to form a custom component • Domain specific language called JSX • Customisable with CSS • Or better “usually match how CSS works on the web”
  27. https://facebook.github.io/react-native/docs/components-and-apis.html

  28. // React Native import React from "react"; import { StyleSheet,

    Text, View } from "react-native"; export default class App extends React.Component { render() { return ( <View style={styles.container}> <Text>Hello world!</Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center" } }); // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child: Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }
  29. // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child:

    Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }
  30. // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child:

    Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }
  31. // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child:

    Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); }
  32. // Flutter import 'package:flutter/material.dart'; void main() { runApp( Center( child:

    Text( 'Hello, world!', textDirection: TextDirection.ltr, ), ), ); } • Basic UI building blocks • Takes inspiration from RN • Everything is a Widget Widgets
  33. Structural Element (Button, Menu …)

  34. Stylistic Element (Font, Color Scheme ..)

  35. Aspect of Layout (Padding, Align ..)

  36. https://flutter.io/docs/development/ui/widgets

  37. Components vs Widgets: Summary • React Native: jumps from Javascript

    to JSX • Flutter: remains in the Dart context • Possibility of UI modularisation
  38. Components vs Widgets: Summary • React Native: jumps from Javascript

    to JSX • Flutter: remains in the Dart context • Possibility of UI modularisation
  39. State Management • You should do it! • Separation of

    presentation logic from business logic • Data sync from different components/widget
 
 … • React Native: “Naive method”, Redux, .. • Flutter: “Naive method”, Scoped Model, BLoC, Redux, ..
  40. State Management - Flutter • https://www.youtube.com/watch?v=PLHln7wHgPE • https://www.youtube.com/watch?v=RS36gBEp8OI • https://www.youtube.com/watch?v=d_m5csmrf7I

    • http://fluttersamples.com/
  41. Declarative UI • Imperative style: retrieve an instance from the

    view owner and update it based on the new state • Describe the current UI state and the framework manages state changes
  42. None
  43. Jetpack Compose https://developer.android.com/jetpack/compose

  44. Jetpack Compose • Kotlin based • Composable function that transform

    application data to UI hierarchy import androidx.compose.* import androidx.ui.core.* @Composable fun Greeting(name: String) { Text ("Hello $name!") }
  45. None
  46. https://developer.apple.com/xcode/swiftui/

  47. https://developer.apple.com/xcode/swiftui/

  48. UNDER THE HOOD

  49. React Native • Core: an infrastructure, aka “Bridge” built at

    runtime • It lets native code call JS and viceversa • Your code run inside a JS Virtual Machine: JavaScriptCore • Event driven
  50. • Event driven Event Serialized Payload Process Event Process Command

    Serialized Response Call native methods App opening [1, 1, [‘My App’, {}]] [[2, 3, [2, ‘View’, {…}]],
 [2, 3, [3, ‘View’, {…}]]] val view = View()
 val view = TextView() Render new Views
  51. • Calls passed between JS to Native in a “batched

    asynchronous way” • quequed in the MessageQueue -> flushed every 5 ms by default • Event driven
  52. New RN Architecture • React Native team is working on

    a new architecture: Fabric • High priority UI updates synchronously • No more bridge and serialisation • JSI (JavaScript Interface) between JS and Native Code https://www.youtube.com/watch?v=UcqRXTriUVI
  53. Flutter • Dart code compiled into native, ARM and x86

    libraries • Widgets are managed and rendered using a C++ engine Framework (Dart) Engine (C++) Skia Dart Text Material Cupertino Widgets Rendering Animation Painting Gestures Foundation
  54. Flutter • Dart code compiled into native, ARM and x86

    libraries • Widgets are managed and rendered using a C++ engine • All elements are rendered with Skia, a 2-d graphics library • Pro: take advantage of the GPU • Cons: app size is larger
  55. Recap • Components translated to native • Use Native components

    • Delay due to Bridge initialisation and runtime translation • Widget independent of the OS • No translation time needed • Include its own widgets
  56. Fast Development Expressive and Flexible UI Native Performance Flutter Features

  57. Common Interesting Features: • Hot reload without losing state

  58. • Hot reload without losing state • Build on top

    of Hot Module Replacement by Webpack • HMR runtime included in the app that receives new module and replace it
  59. • Hot reload without losing state • State is maintained

    during builds • Thanks to a mix of Ahead- of-time (AOT) and Just-In- Time (JIT) compilation
  60. Common Interesting Features: • Hot reload without losing state •

    Update only components/widget that have changed
  61. • Update only components/widget that have changed • Virtual DOM

    as representation of the UI <button class='button button-blue'> <b> OK! </b> </button> { type: 'button', props: { className: 'button button-blue', children: { type: 'b', props: { children: 'OK!' } } } }
  62. • Update only components/widget that have changed • Virtual DOM

    as representation of the UI • Diff comparison using reconciliation • O(n) heuristic algorithm thanks to two assumption: • Two elements of different types will produce different trees. • The developer can hint at which child elements may be stable across different renders with a key prop.
  63. • Update only components/widget that have changed • Element Tree

    as representation of the UI
  64. • Update only components/widget that have changed • Element Tree

    as representation of the UI • After an user input or other stimuli a widget must be redrawn • Not a tree-diffing algorithm • For each element, the child list is examined independently 
 (O(n) algorithm)
  65. Common Interesting Features: • Hot reload without losing state •

    Update only components/widget that have changed • “Frankestein” App
  66. • “Frankestein” App • Add new React Native based features,

    screens, views, etc. in an existing application • Useful for “evolving features” • A view in the native app is a container for the RN component
  67. • “Frankestein” App

  68. • “Frankestein” App

  69. EXAMPLE

  70. render() { return ( <View > <StatusBar backgroundColor="#1976D2" barStyle="light-content" />

    <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> </View> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, }, icon: { marginEnd: 10, padding: 20 }, });
  71. render() { return ( <View > <StatusBar backgroundColor="#1976D2" barStyle="light-content" />

    <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => {
  72. render() { return ( <View > <StatusBar backgroundColor="#1976D2" barStyle="light-content" />

    <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => {
  73. barStyle="light-content" /> <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label}

    containerStyle={styles.container} rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} />
  74. data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId ==

    index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label}
  75. /> <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container}

    rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> </View> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, } });
  76. data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId ==

    index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label}
  77. renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index

    ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> </View> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, }, icon: { marginEnd: 10, padding: 20 }, });
  78. title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop"

    size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state}
  79. render() { return ( <View > <StatusBar backgroundColor="#1976D2" barStyle="light-content" />

    <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem title={item.label} containerStyle={styles.container} rightIcon={this.state.playingId == index ? <Icon style={styles.icon} color="black" name="stop" size={20} onPress={() => { ... this.setState({ ... }) }} /> : <Icon style={styles.icon} color="black" name="play" size={20} onPress={() => { this.setState({ ... }) ... }} />} /> )} extraData={this.state} keyExtractor={item => item.label} /> </View> ); } const styles = StyleSheet.create({ container: { borderRadius: 5, backgroundColor: "#F3F3F3", marginHorizontal: 10, marginVertical: 5, }, icon: { marginEnd: 10, padding: 20 }, });
  80. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length, ), ), ); }
  81. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name),
  82. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name),
  83. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name),
  84. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name),
  85. Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Flutter

    vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row(
  86. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... <FlatList data={this.state.items} renderItem={(item, index) => ( <ListItem> ... </ListItem> ... > </FlatList>
  87. body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) {

    return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() {
  88. horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius:

    new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); },
  89. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length, ), ), ); }
  90. mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new

    Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length,
  91. @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title:

    Text("Flutter vs React - Flutter Example"), ), body: Container( child: ListView.builder( itemBuilder: (BuildContext context, int index) { return Material( child: Container( margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 10.0), decoration: new BoxDecoration( color: Colors.grey.shade300.withOpacity(0.3), borderRadius: new BorderRadius.circular(5.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text(_items[index].name), IconButton( icon: _playing ? new Icon(Icons.stop) : new Icon(Icons.play_arrow), onPressed: () { ... setState(() { ... }); }), ], ), ), ); }, itemCount: _items.length, ), ), ); }
  92. Source Code bit.ly/react-native-sample bit.ly/flutter-sample bit.ly/flutter-better-sample

  93. CONCLUSIONS

  94. Crossplatform • Crossplatform is not bad but… IS NOT better

    than native • It’s a choice with compromises based on specific situation • If trouble became higher than benefits, make a step back
  95. React Native or Flutter ? • Right now, React Native

    is more stable and solid • Flutter is the future • If Google does not drop it $ • Better performance that other framework • Dart is a more modern language
  96. Flutter for Web • Rendering using standards-based web technologies: HTML,

    CSS and JavaScript https://flutter.dev/web
  97. Desktop support https://flutter.dev/desktop

  98. Bibliography / Useful Links • https://flutter.dev/docs/development/ui/widgets-intro • https://flutter.dev/docs/get-started/flutter-for/react-native-devs • https://facebook.github.io/react-native/docs/components-and-apis.html

    • https://levelup.gitconnected.com/wait-what-happens-when-my-react-native-application-starts-an-in-depth-look-inside-react-native-5f306ef3250f • https://flutter.dev/docs/resources/faq • https://flutter.dev/docs/resources/technical-overview • https://speakerdeck.com/mkonicek/under-the-hood-of-react-native • https://speakerdeck.com/frantic/react-native-under-the-hood • https://www.youtube.com/watch?v=rReCzR6DMEM • https://facebook.github.io/react-native/blog/2016/03/24/introducing-hot-reloading • https://flutter.dev/docs/development/tools/hot-reload • https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html • https://reactjs.org/docs/reconciliation.html • https://flutter.dev/docs/resources/inside-flutter • https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps • https://facebook.github.io/react-native/docs/integration-with-existing-apps • https://medium.com/snapp-mobile/multi-vs-cross-platform-in-the-age-of-flutter-6e76920028b6 • https://medium.com/dartlang/announcing-dart-2-80ba01f43b6 • https://medium.com/airbnb-engineering/sunsetting-react-native-1868ba28e30a • https://medium.com/flutter-io/hummingbird-building-flutter-for-the-web-e687c2a023a8
  99. THANK YOU! twitter.com/marcoGomier github.com/prof18 marco.gomiero.93[at]gmail[dot]com marcogomiero.com