SlideShare uma empresa Scribd logo
1 de 37
Flutter: do zero a
publicação
Cícero Duarte / Cinthia Galvão
Cícero Duarte
linkedin.com/in/ciceroduarte
github.com/ciceroduarte
Desenvolvedor iOS
Cinthia Galvão
linkedin.com/in/cinthiagalvao
github.com/cpgalvao
Desenvolvedora Android
Agenda
- Flutter
- Visão geral
- Demo
- Integração com código nativo
- Geração de versão
- Case UOL VivaBem
- Prós / Contras
Motivação
- Oportunidade
- Flutter
- Possível case Google/IO
- App publicado até final de abril
O que é Flutter?
- SDK de desenvolvimento multiplataforma
- Criado pelo Google
- Desempenho
- UI rica e nativa
- Desenvolvimento rápido
- 11/05/2017: Primeira release 0.0.6
- 20/06/2018: Release Preview 1
Instalação
- Entrar em: https://flutter.io/get-started/install/
- Extrair em um diretório e adicionar ao $PATH
$ export PATH=`pwd`/flutter/bin:$PATH
$ flutter doctor
Atualização
$ flutter upgrade
Arquitetura em camadas
Engine (C++) Skia Dart Text
Framework (Dart)
Animation Painting Gestures
Foundation
Rendering
Widgets
Material Cupertino
Dart
- Apresentada pelo Google em 2011
- Substituir o Javascript
- VM ou compilada para Javascript
- Utilizada em produtos internos no Google
Flutter + Dart
- Orientada a objetos
- Opcionalmente tipada
- Declarativa
- StyleGuide bem definido
- Compila para ARM Code
- Ahead-of-time
- Just-in-time
+ =
Ahead-of-time
Just-in-time
🤖
Widgets
Container Column Row Stack Center Padding
Appbar FloatingActionButton TabBar BottomNavigationBar TextField SimpleDialog
StatefulWidgetStatelessWidget
Widget
AssetImage Text Scrollable Animatable
Widgets
Stateless - Imutável,
desenhada apenas uma vez
Stateful - Mutável, método
setState redesenha a widget
AboutPage DetailPage
Construindo um layout
Demo
Internacionalização
dependencies:
flutter_localizations:
sdk: flutter
intl:
intl_translation:
localizationsDelegates: [
// ... app-specific localization delegate[s] here
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', 'US'),
const Locale('pt', 'BR'),
// ... other locales the app supports
],
Importar dependências no pubspec.yaml
Implementar delegates e locales
class DemoLocalizations {
static Future<DemoLocalizations> load(Locale locale) {
final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final String localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((Null _) {
Intl.defaultLocale = localeName;
return DemoLocalizations();
});
}
static DemoLocalizations of(BuildContext context) {
return Localizations.of<DemoLocalizations>(context, DemoLocalizations);
}
String get title {
return Intl.message(
'Hello World',
name: 'title',
desc: 'Title for the Demo application',
);
}
}
Implementar classe para Localization e Strings internacionalizadas
Executar comandos
$ flutter pub pub run
intl_translation:extract_to_arb
—output-dir=lib/i18n lib/main.dart$ flutter pub pub run
intl_translation:generate_from_arb
--output-dir=lib/i18n
--no-use-deferred-loading
lib/main.dart lib/i18n/intl_messages.arb
appBar: AppBar(
title: Text("Comprar"),
)
Internacionalização 🚀
dependencies:
flutter_localizations:
sdk: flutter
intl:
intl_translation:
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
S.delegate,
],
supportedLocales: S.delegate.supportedLocales,
Utilizar o plugin para extrair strings
Demo
MethodChannel
FlutterMethodChannel
MethodChannel
Integração com código nativo
Flutter
State
iOS
AppDelegate
iOS platform
APIs
3rd-Party
APIs for iOS
FlutterViewController
Android
Activity
Android
platform APIs
3rd-Party
APIs for
Android
FlutterView
Integração com código nativo
static const platform = const MethodChannel(‘tdc_demo_channel');
final String result = await platform.invokeMethod('getNativeText', param);
nativeText = 'Texto final recebido do Nativo: $result';
val channel = MethodChannel(flutterView, "tdc_demo_channel")
channel.setMethodCallHandler { call, result ->
if (call.method == "getNativeText") {
var resultString = getString(R.string.platform_string)
result.success("$resultString ${call.arguments}")
} else {
result.notImplemented()
}
}
let channel = FlutterMethodChannel(name: “tdc_demo_channel”, binaryMessenger: controller)
channel.setMethodCallHandler { (call, result) in
if call.method == "getNativeText" {
let resultString = "Método iOS, parâmetro: (call.arguments ?? "")"
result(resultString + "($0 ?? "")")
} else {
result(FlutterMethodNotImplemented)
}
}
Integração com código nativo
static const platform = const MethodChannel(‘tdc_demo_channel');
final String result = await platform.invokeMethod('getNativeText', param);
nativeText = 'Texto final recebido do Nativo: $result';
val channel = MethodChannel(flutterView, "tdc_demo_channel")
channel.setMethodCallHandler { call, result ->
if (call.method == "getNativeText") {
var resultString = getString(R.string.platform_string)
result.success("$resultString ${call.arguments}")
} else {
result.notImplemented()
}
}
let channel = FlutterMethodChannel(name: “tdc_demo_channel”, binaryMessenger: controller)
channel.setMethodCallHandler { (call, result) in
if call.method == "getNativeText" {
let resultString = "Método iOS, parâmetro: (call.arguments ?? "")"
result(resultString + "($0 ?? "")")
} else {
result(FlutterMethodNotImplemented)
}
}
Integração com código nativo
static const platform = const MethodChannel(‘tdc_demo_channel');
final String result = await platform.invokeMethod('getNativeText', param);
nativeText = 'Texto final recebido do Nativo: $result';
val channel = MethodChannel(flutterView, "tdc_demo_channel")
channel.setMethodCallHandler { call, result ->
if (call.method == "getNativeText") {
var resultString = getString(R.string.platform_string)
result.success("$resultString ${call.arguments}")
} else {
result.notImplemented()
}
}
let channel = FlutterMethodChannel(name: “tdc_demo_channel”, binaryMessenger: controller)
channel.setMethodCallHandler { (call, result) in
if call.method == "getNativeText" {
let resultString = "Método iOS, parâmetro: (call.arguments ?? "")"
result(resultString + "($0 ?? "")")
} else {
result(FlutterMethodNotImplemented)
}
}
NativePageState() {
platform.setMethodCallHandler(_handlerNativeCall);
}
Future<dynamic> _handlerNativeCall(MethodCall call) async {
switch (call.method) {
case "getFlutterText":
return Future.value("Método Flutter, parâmetro: ${call.arguments}");
}
}
channel.invokeMethod("getFlutterText", arguments: "iOSParam", result: {
print(resultString + "($0 ?? "")")
})
channel.invokeMethod(“getFlutterText", “AndroidParam”, object : MethodChannel.Result {
override fun success(p0: Any?) {
resultString = "$resultString $p0"
print(resultString)
}
override fun error(p0: String?, p1: String?, p2: Any?) { }
override fun notImplemented() { }
})
Integração com código nativo
NativePageState() {
platform.setMethodCallHandler(_handlerNativeCall);
}
Future<dynamic> _handlerNativeCall(MethodCall call) async {
switch (call.method) {
case "getFlutterText":
return Future.value("Método Flutter, parâmetro: ${call.arguments}");
}
}
channel.invokeMethod("getFlutterText", arguments: "iOSParam", result: {
print(resultString + "($0 ?? "")")
})
channel.invokeMethod(“getFlutterText", “AndroidParam”, object : MethodChannel.Result {
override fun success(p0: Any?) {
resultString = "$resultString $p0"
print(resultString)
}
override fun error(p0: String?, p1: String?, p2: Any?) { }
override fun notImplemented() { }
})
Integração com código nativo
NativePageState() {
platform.setMethodCallHandler(_handlerNativeCall);
}
Future<dynamic> _handlerNativeCall(MethodCall call) async {
switch (call.method) {
case "getFlutterText":
return Future.value("Método Flutter, parâmetro: ${call.arguments}");
}
}
channel.invokeMethod("getFlutterText", arguments: "iOSParam", result: {
print(resultString + "($0 ?? "")")
})
channel.invokeMethod(“getFlutterText", “AndroidParam”, object : MethodChannel.Result {
override fun success(p0: Any?) {
resultString = "$resultString $p0"
print(resultString)
}
override fun error(p0: String?, p1: String?, p2: Any?) { }
override fun notImplemented() { }
})
Integração com código nativo
Gerando versão Android
$ flutter clean
$ flutter build apk --release
$ zipalign -v -p 4
app-release.apk app-release-final.apk
$ apksigner sign --ks <my-release-key.jks>
--out app-release-final-assinada.apk
app-release-final.apk
$ apksigner verify --print-certs
app-release-final-assinada.apk
Gerando versão iOS
$ flutter clean
$ flutter build ios --release
$ open ios/Runner.xcworkspace
Case
- VivaBem
- Canal de saúde e bem-estar do UOL
- Aplicativo
- Meditação e mindfulness
- Notícias e blogs
- Lembretes
- Aplicativo atraente
- Componentes de UI
- Animações
- Funcionalidades do app
- Reprodução de áudio
- Google Analytics
- Notificações
Case
16/02
20/02
28/02
26/03
23/04
03/05
Proposta do case
Início de POCs
POCs -> início
do projeto
Publicação nas lojas
Android e iOS.
Reunião com cliente
sobre app
Versão release
candidate
Confirmação
SandBox area
no Google I/O
Case
Case
Prós Contras
- Desempenho
- Hot reload
- Integração com código nativo
- Integridade dos layouts
- Webview/Maps
- Integração com views nativas
- Falta de componentes nativos
- Suporte para devices 32bits
- Suporte para Android SDK16+
Links
- Flutter
- https://flutter.io/
- Instalação/Update do ambiente
- https://flutter.io/get-started/install/
- https://flutter.io/upgrading/
- Widgets
- https://flutter.io/tutorials/layout/
- https://flutter.io/widgets/
- Internacionalização
- https://flutter.io/tutorials/internationalization/
- Integração com código nativo
- https://flutter.io/platform-channels/
- Showcase
- https://flutter.io/showcase/
Cícero Duarte
linkedin.com/in/ciceroduarte
Cinthia Galvão
linkedin.com/in/cinthiagalvao
https://github.com/cpgalvao/tdc_demo

Mais conteúdo relacionado

Mais procurados

Curso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP BásicoCurso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP BásicoNorton Guimarães
 
10 Java Script - Exemplos práticos
10 Java Script - Exemplos práticos10 Java Script - Exemplos práticos
10 Java Script - Exemplos práticosCentro Paula Souza
 
Aula de Introdução - JAVA
Aula de Introdução  - JAVAAula de Introdução  - JAVA
Aula de Introdução - JAVAMoises Omena
 
Projeto e Desenvolvimento de Software
Projeto e Desenvolvimento de SoftwareProjeto e Desenvolvimento de Software
Projeto e Desenvolvimento de SoftwareAragon Vieira
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POODaniel Brandão
 
Metodologia orientado a objetos
Metodologia orientado a objetosMetodologia orientado a objetos
Metodologia orientado a objetosGabriel Faustino
 
Desenvolvimento de Sistemas Web - Conceitos Básicos
Desenvolvimento de Sistemas Web - Conceitos BásicosDesenvolvimento de Sistemas Web - Conceitos Básicos
Desenvolvimento de Sistemas Web - Conceitos BásicosFabio Moura Pereira
 
Introdução a Informática
Introdução a InformáticaIntrodução a Informática
Introdução a InformáticaDaniel Brandão
 
Aula 1 - Programação Dinâmica para Web
Aula 1 - Programação Dinâmica para WebAula 1 - Programação Dinâmica para Web
Aula 1 - Programação Dinâmica para WebDaniel Brandão
 
Aula 02 - UML e Padrões de Projeto
Aula 02 - UML e Padrões de ProjetoAula 02 - UML e Padrões de Projeto
Aula 02 - UML e Padrões de ProjetoVinícius de Paula
 
Exercicios resolvidos visuAlg
Exercicios resolvidos visuAlgExercicios resolvidos visuAlg
Exercicios resolvidos visuAlgWillians Miyabara
 
Aula 1 - Introdução ao Mobile
Aula 1 - Introdução ao MobileAula 1 - Introdução ao Mobile
Aula 1 - Introdução ao MobileCloves da Rocha
 
Aula 6 - Design e Processo de Design de Interfaces de Usuário
Aula 6 - Design e Processo de Design de Interfaces de UsuárioAula 6 - Design e Processo de Design de Interfaces de Usuário
Aula 6 - Design e Processo de Design de Interfaces de UsuárioAndré Constantino da Silva
 
Internet das Coisas: Conceitos e Aplicações
Internet das Coisas: Conceitos e AplicaçõesInternet das Coisas: Conceitos e Aplicações
Internet das Coisas: Conceitos e AplicaçõesFaculdade Martha Falcão
 
Desenvolvimento Mobile
Desenvolvimento MobileDesenvolvimento Mobile
Desenvolvimento MobileElton Minetto
 
Engenharia de Requisitos
Engenharia de RequisitosEngenharia de Requisitos
Engenharia de RequisitosCloves da Rocha
 

Mais procurados (20)

Curso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP BásicoCurso Linguagem de Programação I - PHP Básico
Curso Linguagem de Programação I - PHP Básico
 
10 Java Script - Exemplos práticos
10 Java Script - Exemplos práticos10 Java Script - Exemplos práticos
10 Java Script - Exemplos práticos
 
Aula de Introdução - JAVA
Aula de Introdução  - JAVAAula de Introdução  - JAVA
Aula de Introdução - JAVA
 
Projeto e Desenvolvimento de Software
Projeto e Desenvolvimento de SoftwareProjeto e Desenvolvimento de Software
Projeto e Desenvolvimento de Software
 
Oficina Scratch
Oficina ScratchOficina Scratch
Oficina Scratch
 
Aula 1 - Introdução a POO
Aula 1 -  Introdução a POOAula 1 -  Introdução a POO
Aula 1 - Introdução a POO
 
Metodologia orientado a objetos
Metodologia orientado a objetosMetodologia orientado a objetos
Metodologia orientado a objetos
 
Curso javascript básico
Curso javascript básicoCurso javascript básico
Curso javascript básico
 
Desenvolvimento de Sistemas Web - Conceitos Básicos
Desenvolvimento de Sistemas Web - Conceitos BásicosDesenvolvimento de Sistemas Web - Conceitos Básicos
Desenvolvimento de Sistemas Web - Conceitos Básicos
 
Introdução a Informática
Introdução a InformáticaIntrodução a Informática
Introdução a Informática
 
Aula 1 - Programação Dinâmica para Web
Aula 1 - Programação Dinâmica para WebAula 1 - Programação Dinâmica para Web
Aula 1 - Programação Dinâmica para Web
 
Curso de Desenvolvimento Web - Módulo 01 - HTML
Curso de Desenvolvimento Web - Módulo 01 - HTMLCurso de Desenvolvimento Web - Módulo 01 - HTML
Curso de Desenvolvimento Web - Módulo 01 - HTML
 
Aula 02 - UML e Padrões de Projeto
Aula 02 - UML e Padrões de ProjetoAula 02 - UML e Padrões de Projeto
Aula 02 - UML e Padrões de Projeto
 
Python - Introdução
Python - IntroduçãoPython - Introdução
Python - Introdução
 
Exercicios resolvidos visuAlg
Exercicios resolvidos visuAlgExercicios resolvidos visuAlg
Exercicios resolvidos visuAlg
 
Aula 1 - Introdução ao Mobile
Aula 1 - Introdução ao MobileAula 1 - Introdução ao Mobile
Aula 1 - Introdução ao Mobile
 
Aula 6 - Design e Processo de Design de Interfaces de Usuário
Aula 6 - Design e Processo de Design de Interfaces de UsuárioAula 6 - Design e Processo de Design de Interfaces de Usuário
Aula 6 - Design e Processo de Design de Interfaces de Usuário
 
Internet das Coisas: Conceitos e Aplicações
Internet das Coisas: Conceitos e AplicaçõesInternet das Coisas: Conceitos e Aplicações
Internet das Coisas: Conceitos e Aplicações
 
Desenvolvimento Mobile
Desenvolvimento MobileDesenvolvimento Mobile
Desenvolvimento Mobile
 
Engenharia de Requisitos
Engenharia de RequisitosEngenharia de Requisitos
Engenharia de Requisitos
 

Semelhante a Flutter do zero

TDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacaoTDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacaotdc-globalcode
 
Java orientação a objetos (interfaces)
Java   orientação a objetos (interfaces)Java   orientação a objetos (interfaces)
Java orientação a objetos (interfaces)Armando Daniel
 
Golang para desenvolvedores pragmáticos parte 2
Golang para desenvolvedores pragmáticos  parte 2Golang para desenvolvedores pragmáticos  parte 2
Golang para desenvolvedores pragmáticos parte 2Wilson Júnior
 
Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesLuis Gustavo Almeida
 
Compus Party - processing e arduino
Compus Party - processing e arduinoCompus Party - processing e arduino
Compus Party - processing e arduinoCampus Party Brasil
 
Curso de Introdução ao Android Básico
Curso de Introdução ao Android BásicoCurso de Introdução ao Android Básico
Curso de Introdução ao Android BásicoLuiz Carvalho
 
Ecosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javEcosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javJulio Viegas
 
Python: Cabe no seu bolso, no seu micro, no seu cérebro.
Python: Cabe no seu bolso, no seu micro, no seu cérebro.Python: Cabe no seu bolso, no seu micro, no seu cérebro.
Python: Cabe no seu bolso, no seu micro, no seu cérebro.Rodrigo Senra
 
TDC 2015 - Execução em Background e Live Tiles em Universal Apps
TDC 2015 - Execução em Background e Live Tiles em Universal AppsTDC 2015 - Execução em Background e Live Tiles em Universal Apps
TDC 2015 - Execução em Background e Live Tiles em Universal AppsDiego Castro
 
PyData - Consumindo e publicando web APIs com Python
PyData - Consumindo e publicando web APIs com PythonPyData - Consumindo e publicando web APIs com Python
PyData - Consumindo e publicando web APIs com PythonBruno Rocha
 
Integração do Flex com PHP através do AMFPHP
Integração do Flex com PHP através do AMFPHPIntegração do Flex com PHP através do AMFPHP
Integração do Flex com PHP através do AMFPHPelliando dias
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Luis Gustavo Almeida
 
O que esperar do Zend Framework 3
O que esperar do Zend Framework 3O que esperar do Zend Framework 3
O que esperar do Zend Framework 3Flávio Lisboa
 
C#4 - Parte 2 - COM interop e variância
C#4 - Parte 2 - COM interop e variânciaC#4 - Parte 2 - COM interop e variância
C#4 - Parte 2 - COM interop e variânciaGiovanni Bassi
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Michael Castillo Granados
 

Semelhante a Flutter do zero (20)

TDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacaoTDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
 
Flutter do zero a publicacao
Flutter do zero a publicacaoFlutter do zero a publicacao
Flutter do zero a publicacao
 
Java orientação a objetos (interfaces)
Java   orientação a objetos (interfaces)Java   orientação a objetos (interfaces)
Java orientação a objetos (interfaces)
 
Python 08
Python 08Python 08
Python 08
 
Golang para desenvolvedores pragmáticos parte 2
Golang para desenvolvedores pragmáticos  parte 2Golang para desenvolvedores pragmáticos  parte 2
Golang para desenvolvedores pragmáticos parte 2
 
Android na Prática
Android na PráticaAndroid na Prática
Android na Prática
 
Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e Routes
 
Compus Party - processing e arduino
Compus Party - processing e arduinoCompus Party - processing e arduino
Compus Party - processing e arduino
 
Curso de Introdução ao Android Básico
Curso de Introdução ao Android BásicoCurso de Introdução ao Android Básico
Curso de Introdução ao Android Básico
 
Ecosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_javEcosistema spring a_plataforma_enterprise_jav
Ecosistema spring a_plataforma_enterprise_jav
 
Python: Cabe no seu bolso, no seu micro, no seu cérebro.
Python: Cabe no seu bolso, no seu micro, no seu cérebro.Python: Cabe no seu bolso, no seu micro, no seu cérebro.
Python: Cabe no seu bolso, no seu micro, no seu cérebro.
 
TDC 2015 - Execução em Background e Live Tiles em Universal Apps
TDC 2015 - Execução em Background e Live Tiles em Universal AppsTDC 2015 - Execução em Background e Live Tiles em Universal Apps
TDC 2015 - Execução em Background e Live Tiles em Universal Apps
 
PyData - Consumindo e publicando web APIs com Python
PyData - Consumindo e publicando web APIs com PythonPyData - Consumindo e publicando web APIs com Python
PyData - Consumindo e publicando web APIs com Python
 
Integração do Flex com PHP através do AMFPHP
Integração do Flex com PHP através do AMFPHPIntegração do Flex com PHP através do AMFPHP
Integração do Flex com PHP através do AMFPHP
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
O que esperar do Zend Framework 3
O que esperar do Zend Framework 3O que esperar do Zend Framework 3
O que esperar do Zend Framework 3
 
Mock Objects
Mock ObjectsMock Objects
Mock Objects
 
C#4 - Parte 2 - COM interop e variância
C#4 - Parte 2 - COM interop e variânciaC#4 - Parte 2 - COM interop e variância
C#4 - Parte 2 - COM interop e variância
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014
 
Android wear
Android wearAndroid wear
Android wear
 

Flutter do zero

  • 1. Flutter: do zero a publicação Cícero Duarte / Cinthia Galvão
  • 2. Cícero Duarte linkedin.com/in/ciceroduarte github.com/ciceroduarte Desenvolvedor iOS Cinthia Galvão linkedin.com/in/cinthiagalvao github.com/cpgalvao Desenvolvedora Android
  • 3. Agenda - Flutter - Visão geral - Demo - Integração com código nativo - Geração de versão - Case UOL VivaBem - Prós / Contras
  • 4. Motivação - Oportunidade - Flutter - Possível case Google/IO - App publicado até final de abril
  • 5. O que é Flutter? - SDK de desenvolvimento multiplataforma - Criado pelo Google - Desempenho - UI rica e nativa - Desenvolvimento rápido - 11/05/2017: Primeira release 0.0.6 - 20/06/2018: Release Preview 1
  • 6. Instalação - Entrar em: https://flutter.io/get-started/install/ - Extrair em um diretório e adicionar ao $PATH $ export PATH=`pwd`/flutter/bin:$PATH $ flutter doctor
  • 8. Arquitetura em camadas Engine (C++) Skia Dart Text Framework (Dart) Animation Painting Gestures Foundation Rendering Widgets Material Cupertino
  • 9. Dart - Apresentada pelo Google em 2011 - Substituir o Javascript - VM ou compilada para Javascript - Utilizada em produtos internos no Google
  • 10. Flutter + Dart - Orientada a objetos - Opcionalmente tipada - Declarativa - StyleGuide bem definido - Compila para ARM Code - Ahead-of-time - Just-in-time + =
  • 13. Widgets Container Column Row Stack Center Padding Appbar FloatingActionButton TabBar BottomNavigationBar TextField SimpleDialog
  • 14. StatefulWidgetStatelessWidget Widget AssetImage Text Scrollable Animatable Widgets Stateless - Imutável, desenhada apenas uma vez Stateful - Mutável, método setState redesenha a widget AboutPage DetailPage
  • 16. Demo
  • 17. Internacionalização dependencies: flutter_localizations: sdk: flutter intl: intl_translation: localizationsDelegates: [ // ... app-specific localization delegate[s] here GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], supportedLocales: [ const Locale('en', 'US'), const Locale('pt', 'BR'), // ... other locales the app supports ], Importar dependências no pubspec.yaml Implementar delegates e locales
  • 18. class DemoLocalizations { static Future<DemoLocalizations> load(Locale locale) { final String name = locale.countryCode.isEmpty ? locale.languageCode : locale.toString(); final String localeName = Intl.canonicalizedLocale(name); return initializeMessages(localeName).then((Null _) { Intl.defaultLocale = localeName; return DemoLocalizations(); }); } static DemoLocalizations of(BuildContext context) { return Localizations.of<DemoLocalizations>(context, DemoLocalizations); } String get title { return Intl.message( 'Hello World', name: 'title', desc: 'Title for the Demo application', ); } } Implementar classe para Localization e Strings internacionalizadas
  • 19. Executar comandos $ flutter pub pub run intl_translation:extract_to_arb —output-dir=lib/i18n lib/main.dart$ flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/i18n --no-use-deferred-loading lib/main.dart lib/i18n/intl_messages.arb
  • 20. appBar: AppBar( title: Text("Comprar"), ) Internacionalização 🚀 dependencies: flutter_localizations: sdk: flutter intl: intl_translation: localizationsDelegates: [ GlobalMaterialLocalizations.delegate, S.delegate, ], supportedLocales: S.delegate.supportedLocales, Utilizar o plugin para extrair strings
  • 21. Demo
  • 22. MethodChannel FlutterMethodChannel MethodChannel Integração com código nativo Flutter State iOS AppDelegate iOS platform APIs 3rd-Party APIs for iOS FlutterViewController Android Activity Android platform APIs 3rd-Party APIs for Android FlutterView
  • 23. Integração com código nativo static const platform = const MethodChannel(‘tdc_demo_channel'); final String result = await platform.invokeMethod('getNativeText', param); nativeText = 'Texto final recebido do Nativo: $result'; val channel = MethodChannel(flutterView, "tdc_demo_channel") channel.setMethodCallHandler { call, result -> if (call.method == "getNativeText") { var resultString = getString(R.string.platform_string) result.success("$resultString ${call.arguments}") } else { result.notImplemented() } } let channel = FlutterMethodChannel(name: “tdc_demo_channel”, binaryMessenger: controller) channel.setMethodCallHandler { (call, result) in if call.method == "getNativeText" { let resultString = "Método iOS, parâmetro: (call.arguments ?? "")" result(resultString + "($0 ?? "")") } else { result(FlutterMethodNotImplemented) } }
  • 24. Integração com código nativo static const platform = const MethodChannel(‘tdc_demo_channel'); final String result = await platform.invokeMethod('getNativeText', param); nativeText = 'Texto final recebido do Nativo: $result'; val channel = MethodChannel(flutterView, "tdc_demo_channel") channel.setMethodCallHandler { call, result -> if (call.method == "getNativeText") { var resultString = getString(R.string.platform_string) result.success("$resultString ${call.arguments}") } else { result.notImplemented() } } let channel = FlutterMethodChannel(name: “tdc_demo_channel”, binaryMessenger: controller) channel.setMethodCallHandler { (call, result) in if call.method == "getNativeText" { let resultString = "Método iOS, parâmetro: (call.arguments ?? "")" result(resultString + "($0 ?? "")") } else { result(FlutterMethodNotImplemented) } }
  • 25. Integração com código nativo static const platform = const MethodChannel(‘tdc_demo_channel'); final String result = await platform.invokeMethod('getNativeText', param); nativeText = 'Texto final recebido do Nativo: $result'; val channel = MethodChannel(flutterView, "tdc_demo_channel") channel.setMethodCallHandler { call, result -> if (call.method == "getNativeText") { var resultString = getString(R.string.platform_string) result.success("$resultString ${call.arguments}") } else { result.notImplemented() } } let channel = FlutterMethodChannel(name: “tdc_demo_channel”, binaryMessenger: controller) channel.setMethodCallHandler { (call, result) in if call.method == "getNativeText" { let resultString = "Método iOS, parâmetro: (call.arguments ?? "")" result(resultString + "($0 ?? "")") } else { result(FlutterMethodNotImplemented) } }
  • 26. NativePageState() { platform.setMethodCallHandler(_handlerNativeCall); } Future<dynamic> _handlerNativeCall(MethodCall call) async { switch (call.method) { case "getFlutterText": return Future.value("Método Flutter, parâmetro: ${call.arguments}"); } } channel.invokeMethod("getFlutterText", arguments: "iOSParam", result: { print(resultString + "($0 ?? "")") }) channel.invokeMethod(“getFlutterText", “AndroidParam”, object : MethodChannel.Result { override fun success(p0: Any?) { resultString = "$resultString $p0" print(resultString) } override fun error(p0: String?, p1: String?, p2: Any?) { } override fun notImplemented() { } }) Integração com código nativo
  • 27. NativePageState() { platform.setMethodCallHandler(_handlerNativeCall); } Future<dynamic> _handlerNativeCall(MethodCall call) async { switch (call.method) { case "getFlutterText": return Future.value("Método Flutter, parâmetro: ${call.arguments}"); } } channel.invokeMethod("getFlutterText", arguments: "iOSParam", result: { print(resultString + "($0 ?? "")") }) channel.invokeMethod(“getFlutterText", “AndroidParam”, object : MethodChannel.Result { override fun success(p0: Any?) { resultString = "$resultString $p0" print(resultString) } override fun error(p0: String?, p1: String?, p2: Any?) { } override fun notImplemented() { } }) Integração com código nativo
  • 28. NativePageState() { platform.setMethodCallHandler(_handlerNativeCall); } Future<dynamic> _handlerNativeCall(MethodCall call) async { switch (call.method) { case "getFlutterText": return Future.value("Método Flutter, parâmetro: ${call.arguments}"); } } channel.invokeMethod("getFlutterText", arguments: "iOSParam", result: { print(resultString + "($0 ?? "")") }) channel.invokeMethod(“getFlutterText", “AndroidParam”, object : MethodChannel.Result { override fun success(p0: Any?) { resultString = "$resultString $p0" print(resultString) } override fun error(p0: String?, p1: String?, p2: Any?) { } override fun notImplemented() { } }) Integração com código nativo
  • 29. Gerando versão Android $ flutter clean $ flutter build apk --release $ zipalign -v -p 4 app-release.apk app-release-final.apk $ apksigner sign --ks <my-release-key.jks> --out app-release-final-assinada.apk app-release-final.apk $ apksigner verify --print-certs app-release-final-assinada.apk
  • 30. Gerando versão iOS $ flutter clean $ flutter build ios --release $ open ios/Runner.xcworkspace
  • 31. Case - VivaBem - Canal de saúde e bem-estar do UOL - Aplicativo - Meditação e mindfulness - Notícias e blogs - Lembretes
  • 32. - Aplicativo atraente - Componentes de UI - Animações - Funcionalidades do app - Reprodução de áudio - Google Analytics - Notificações Case
  • 33. 16/02 20/02 28/02 26/03 23/04 03/05 Proposta do case Início de POCs POCs -> início do projeto Publicação nas lojas Android e iOS. Reunião com cliente sobre app Versão release candidate Confirmação SandBox area no Google I/O Case
  • 34. Case
  • 35. Prós Contras - Desempenho - Hot reload - Integração com código nativo - Integridade dos layouts - Webview/Maps - Integração com views nativas - Falta de componentes nativos - Suporte para devices 32bits - Suporte para Android SDK16+
  • 36. Links - Flutter - https://flutter.io/ - Instalação/Update do ambiente - https://flutter.io/get-started/install/ - https://flutter.io/upgrading/ - Widgets - https://flutter.io/tutorials/layout/ - https://flutter.io/widgets/ - Internacionalização - https://flutter.io/tutorials/internationalization/ - Integração com código nativo - https://flutter.io/platform-channels/ - Showcase - https://flutter.io/showcase/

Notas do Editor

  1. [Cinthia] Vamos falar de Flutter, uma visão geral, vamos fazer uma demo, mostrar integração com código Android e iOS, como gerar uma versão para publicar. Também iremos mostrar nosso case que foi destaque no Google I/O, e fechar com prós e contras do Flutter
  2. [Cinthia] O que nos levou a descobrir o Flutter? No início do ano, recebemos uma oportunidade/desafio de desenvolver um app em Flutter e esse app tinha chances de ser um case no Google I/O se fosse publicado até o final de abril
  3. [Cinthia] O que é Flutter? É um SDK para desenvolvimento de aplicativos multiplataforma, que foi criado pelo Google e tem como princípios: desempenho, o app desenvolvido tem performance de app nativo; UI rica e nativa, com experiência do usuário natural de cada plataforma; e desenvolvimento rápido, através do uso de widgets e do hot reload. A primeira versão do flutter foi lançada há pouco mais de 1 ano e atualmente está na versão Release Preview 1.
  4. [Cícero] Para iniciar o desenvolvimento em Flutter, é necessário baixar a SDK, extrair o conteúdo do zip e adicionar o diretório onde foi extraído o flutter, no path. A partir daí, pode ser feito um flutter doctor em um terminal para validar a instalação. Pode ser utilizado o Android Studio ou o IntelliJ, adicionando os plugins do Flutter e do Dart, ou ainda o Visual Studio Code com a extension do Flutter.
  5. [Cícero] Para atualizar a versão do Flutter, que está em constante desenvolvimento, basta executar flutter upgrade. Há também outros 2 comandos que serão bastante utilizados: packages get e packages upgrade. Cada vez que o arquivo pubspec.yaml for alterado, adicionando ou alterando um pacote, será necessário executá-los.
  6. [Cícero] // Falar em camadas O Flutter essencialmente é organizado em camadas, podemos separar em duas camadas principais, a Engine e o Framework. A Engine é a camada escrita em C/C++ que compõe a estrutura de execução, tendo a Skia, uma biblioteca de renderização 2D e de texto, que também é utilizada por exemplo no Google Chrome e no próprio Android e além da Skia, tem o Dart, que é a linguagem que utilizamos para desenvolver em Flutter. A camada verde é o Framework, é a parte totalmente escrita em Dart, ou seja, tudo que você utiliza na ferramenta é escrito em Dart, ela controla toda a parte de renderização, gestures, animações e possui o principal pilar do Flutter, as Widgets. // Falar sobre framework reativo moderno; // APIs de teste Tudo no Flutter são Widgets, não só componentes visuais como TextFields e Labels, Widgets também são utilizadas para estruturar o layout, como as Widgets de Center, Row e Column. Acima das Widgets podemos ver na mesma camada os itens Material e Cupertino, que são os conjuntos de Widgets específicas para Android e iOS, logicamente Material são as de Android e Cupertino as de iOS
  7. [Cícero] Uma das dúvidas mais frequentes sobre o Flutter é: Por que utilizar Dart e não Kotlin, Swift ou Javascript? Para responder essa pergunta temos que analisar as características do Flutter e um pouco da estratégia do Google com relação ao Dart. Eu particularmente nunca tinha ouvido falar em Dart até conhecer o Flutter, então de onde saiu? Apresentada pelo Google a primeira vez em 2011; Objetivo de substituir o Javascript como principal linguagem embutida nos navegadores; Inicialmente podia rodar em uma VM ou compilada para Javascript; Atualmente é utilizada em vários produtos internos no google.
  8. [Cícero] O Dart não é a primeira linguagem padrão para desenvolver em Flutter, inicialmente era desenvolvido em Javascript, mas a ideia do time de desenvolvimento do Flutter era criar a melhor maneira de desenvolver para mobile, e utilizando Javascript complicaria a maneira que eles queriam gerar os binários para publicação. Com isso, começaram a buscar e analisar várias linguagem existentes no mercado e a que teve uma maior pontuação geral foi o Dart, mas pq? É orientada a objetos É declarativa, fazendo com que os layouts sejam montados de maneira parecida com CSS É uma linguagem majoritariamente mantida pelo Google Pode ser tipada Curva de aprendizagem Tem um StyleGuide bem definido Compila para ARM Code E o mais importante quesito que torna o Dart essencial para o Flutter é que ele pode ser compilado tanto em Ahead-of-time e como Just-in-time, mas o que é isso?
  9. [Cícero] O código da aplicação é compilado direto para código ARM nativo, o que possibilita que a aplicação seja inicializadas com performance de uma aplicação nativa.
  10. [Cícero] Com o objetivo de ser a melhor maneira de desenvolver para mobile, um dos principais feedback que o time do Flutter teve foi que um dos pontos que poderiam melhorar era a velocidade do próprio ciclo de desenvolvimento. A maneira mais comum que desenvolvemos é: Escrevemos código, mandamos rodar e esperamos até que o código seja compilado, o pacote seja gerando, instalado no device e no pior dos casos temos que percorrer várias telas até chegar onde acabamos de fazer a alteração, para ver se deu certo. Um dos objetivos do Flutter é cortar esse tempo de espera, é aí que a compilação Just-in-time do Dart cai como uma luva no Flutter, com ela podemos compilar diretamente no device com a aplicação em execução e ver em praticamente tempo real se a alteração deu certo ou não.
  11. [Cícero] // Apresentar na prática, mostrando exemplos de uso e falando sobre os benefícios: Como as Widgets são renderizadas na camada do Flutter, ela apresentam o mesmo layout independente da versão do Android ou iOS, ou seja, você terá um layout moderno em devices antigos sem ter que fazer manobras e nem perder performance. Widgets não são compostas com herança, mas sim com composição.
  12. [Cinthia] As Widgets são divididas em 2 grandes grupos, o primeiro são as Stateless, que são widgets imutáveis, desenhadas apenas uma vez, como exemplo delas temos os labels de texto, imagens, e no nosso código de exemplo, a AboutPage. As outras são as Stateful, que são mutáveis, onde o método setState redesenha a widget. Os exemplos são views Scrollable, Animadas e a DetailPage do nosso código de exemplo.
  13. [Cinthia] Como eu começo construir um layout? A Scaffold Widget permite que itens básicos sejam adicionados na tela, como AppBar, FloatingActionButton, BottomNavigationBar, Drawer, além do conteúdo da tela. Alguns itens de tela, são facilitados, como a ListView, onde cada item pode ser um ListTile, e só é preciso setar o título, o subtítulo e a imagem dos itens, o layout é montado nesse formato.
  14. [Cinthia] Agora vamos ver como ajustar um layout. Este é nosso app, ele mostra uma lista de frutas, e quando clicamos em um item, vemos os detalhes de uma fruta. - temos um layout com a imagem da fruta, nome, preço e quantidade, porém, está ruim assim... então vamos centralizar esses itens (Center), verticalmente também (MainAxisAlignment.center). Salvamos e pronto. Este é o hot-reload, que assim que salvamos, atualiza o app no emulador ou no device. - podemos aumentar o texto da imagem da fruta (tst) - podemos aumentar também a fonte do nome da fruta (tst) - a fonte do preço, vamos também deixar negrito (tst). - podemos também colocar um padding para não ficar tão próximo (Padding) - e não é só layout que podemos mudar e ver o resultado imediatamente, vamos alterar nosso FloatingButton, que ao invés de adicionar um item, vamos remover um item (Icon.remove / count--)
  15. [Cinthia] Para internacionalizar Strings em dart/flutter, devemos importar as dependências de internacionalização no yaml, implementar os delegates e locales na classe do application
  16. [Cinthia] Implementar uma classe para a Localization e descrição de cada uma das Strings internacionalizadas
  17. [Cinthia] E por último, executar os 2 comandos: extract_to_arb, que irá gerar o arquivo arb com as Strings extraídas da classe, onde será possível traduzí-las, e depois o generate_from_arb que irá processar as strings traduzidas.
  18. [Cinthia] Porém, temos uma maneira mais simples e fácil, que é utilizando o plugin Flutter i18n, onde é necessário importar as dependências de internacionalização no yaml, implementar os delegates e locales na classe do app, e extrair e traduzir as Strings utilizando o plugin
  19. [Cícero] Vamos internacionalizar o título da tela de Comprar, então, basta selecionarmos a opção de extrair a string, selecionar a linguagem, e definir um id para essa string. Depois basta fazer este mesmo processo para as demais linguas, ou editar diretamente os arquivos arb
  20. [Cinthia] É possível integrar o código do Flutter ao nativo, que para Android pode ser em Java ou Kotlin, e para iOS pode ser em objective-C ou Swift. Para fazer a integração deve ser utilizado um canal, que pode ser utilizado em ambos os sentidos: para o flutter acessar o código nativo ou para o código nativo acessar o flutter.
  21. [Cinthia] Aqui vemos um exemplo do código Flutter acessando código nativo
  22. primeiramente criamos o channel, que neste caso se chama tdc_demo_channel, e então fazemos um invokeMethod, utilizando esse channel e passando por parâmetro do método invokeMethod, o nome do método nativo e os parâmetros que desejamos enviar ao nativo.
  23. Do lado do nativo, tanto para Android, quanto para iOS, também precisamos criar o channel, com o mesmo nome, e implementar o método setMethodCallHandler, onde iremos validar o conteúdo do método, e então implementar o seu conteúdo. No nosso caso, retornamos uma string, com o valor “Método Android ou iOS” e apendamos a essa string, os parâmetros recebidos do flutter. Por fim, enviamos através do result o resultado do método nativo executado.
  24. [Cícero] Aqui vemos um exemplo do código nativo acessando código flutter.
  25. Da mesma maneira que o sentido inverso, devemos criar o canal, e apenas inverter o que vimos anteriormente: o código nativo chama o método Flutter através do invokeMethod, passando o nome do método Flutter a ser chamado e os parâmetros a serem enviados para esse método. E então implementamos a callback para receber o resultado do método de flutter que foi chamado.
  26. Do lado do flutter, implementamos o setMethodCallHandler para receber o chamado do código nativo, e validar o nome do método, e então implementamos o conteúdo do método, retornando o resultado. Neste caso o retorno seria a string “Método flutter, parâmetro” e os parâmetros recebidos do código nativo.
  27. [Cinthia] Para gerar a versão final do app Android, basta executar o comando flutter build apk release, passar o zipalign, e assinar o apk. A partir daí, é só subir na loja o apk.
  28. [Cícero] Para gerar a versão de iOS, utilizamos o comando flutter build ios release, e abrimos o arquivo do workspace, e então, através do xcode, podemos submeter a versão para a app store
  29. [Cícero] Agora vamos falar sobre o app que nos levou a aprender Flutter! Viva bem é o canal de saúde e bem-estar do UOL. E o objetivo era fazer um aplicativo contendo práticas de meditação e mindfulness, notícias e blogs da área, além de lembretes através de notificações para lembrar o usuário de praticar a meditação
  30. [Cícero] No VivaBem, nosso foco foi utilizar diversos componentes de UI e trabalhar com animações para gerar um aplicativo atraente. E com reprodução de áudio, utilização do google analytics e push notifications para atender os requisitos do app.
  31. [Cinthia] Assim que recebemos a proposta do case e começamos o estudo de Flutter através do desenvolvimento de POCs, de diversos componentes de UI, requests, parser de jsons. Durante os estudos, tivemos uma reunião com o cliente sobre o app e na semana seguinte, iniciamos o projeto. Em 1 mês finalizamos a versão Beta do app e depois de mais 1 mês, quando ficamos aguardando os áudios das meditações e fazendo ajustes no app, publicamos o app nas lojas. E no começo de maio, veio a confirmação que o VivaBem havia sido aprovado para ser um case na SandBox area do Google I/O
  32. [Cinthia] Aqui está um vídeo com uma demo do nosso app. Este vídeo foi utilizado na Sandbox do Flutter no Google I/O, e o app está no site do Flutter, na área de Showcase. Se quiserem baixar nosso app, está nas lojas, do Android e do iOS, e esse QRCode tem os links diretos.
  33. [Cícero]
  34. [Cícero]