Voltar
Por que eu devo ler este artigo:Confira neste artigo um passo a passo para a criação de um ambiente de desenvolvimento com o Flutter, o framework do Google para a construção de aplicativos nativos para as plataformas Android e iOS.

Guia do artigo:

A todo momento surgem soluções do tipo “um código, dois aplicativos” entre as comunidades de desenvolvimento mobile. Isso é natural porque a ideia de escrever um único código que pode ser reutilizado entre aplicações e em diversas plataformas é tentadora tanto para quem financia o projeto, pela possibilidade de manter equipes menores, quanto para o desenvolvedor, que muitas vezes pode utilizar suas habilidades como ponto de partida no estudo de uma tecnologia, reduzindo assim a sua curva de aprendizado. Entretanto, muitas dessas soluções, citadas no fim, tendem a sacrificar a performance para alcançar certa onipresença.

Por exemplo, o Ionic, por executar em uma Webview, pode entregar um aplicativo multiplataforma, mas a um custo de desempenho altíssimo. O React Native, embora utilize código nativo de cada plataforma, ainda precisa de “pontes” que façam a ligação entre as mesmas e a lógica JavaScript da sua aplicação, o que também podem ser um causador de gargalos.

E se pudéssemos gerar código nativo de alto desempenho tanto para Android quanto para iOS, utilizando uma linguagem de alto nível? E se existisse uma biblioteca que nos desse todos os elementos visuais necessários para uma aplicação, seja seguindo o Material Design do Android ou o padrão de design do iOS, que permitisse a criação de aplicativos extremamente elegantes, com animações fluídas? Esse mundo existe e se chama Flutter.

O Flutter foi apresentado pela primeira vez em meados de 2017 pelo Google, mas foi em Dezembro de 2018, que a primeira versão estável foi liberada para o público. Com o Flutter podemos construir aplicativos nativos e de alta qualidade tanto para Android quanto para iOS, respeitando os padrões de cada uma dessas plataformas, a partir de um mesmo código escrito com a linguagem Dart.

Nesse artigo criaremos nosso primeiro aplicativo utilizando o Flutter. Para isso, será necessário realizar a instalação do Flutter SDK, um conjunto de ferramentas e componentes que serão utilizados para construir e compilar a aplicação. Começaremos com a configuração do Visual Studio Code, de forma a integrá-lo com o SDK e, dessa forma, seremos capazes de utilizar o recurso de Hot Reload, bem como o debugger disponibilizado pelo Flutter. Hot Reload é uma tecnologia que agiliza a depuração, diminuindo o tempo necessário para que as alterações feitas no aplicativo sejam enviadas para o dispositivo que executa a aplicação.

Instalando o Flutter SDK

O Flutter SDK pode ser utilizado no Windows, MacOS e Linux. Aqui, abordaremos apenas a instalação em ambiente Windows, mas caso você utilize outro sistema operacional e está tendo problemas para instalar o SDK, deixe um comentário que o ajudaremos. Antes de mais nada, a fim de gerarmos um APK para o Android, também precisaremos do Android SDK, que pode ser obtido pela instalação do Android Studio. Aqui na DevMedia temos um curso que ensina como preparar um ambiente de desenvolvimento Android, que cobre esse passo e pode ser utilizado como consulta, caso você precise de alguma ajuda.

Com o Android SDK instalado, podemos partir para a instalação do Flutter SDK:

  1. Na página de download do Flutter SDK, clique no botão “Windows”.
    Página com as opções de download do Flutter SDK.
    Figura 1. Página com as opções de download do Flutter SDK.
  2. Na sessão “Get the Flutter SDK”, logo abaixo dos requerimentos do sistema, clique no botão flutter_windows_v1.0.0-stable.zip.
    Página de download do Flutter SDK para Windows.
    Figura 2. Página de download do Flutter SDK para Windows.
  3. Na partição C:/ do seu HD, crie um diretório chamado src/ e extraia os arquivos do SDK nesse diretório:
    Diretório C:/src/
    Figura 3. Diretório C:/src/

Agora que realizamos o download do SDK, criaremos uma variável de ambiente do Windows para sermos capazes de utilizar a ferramenta de linha de comando do Flutter através do terminal do Windows:

  1. Na barra de busca do Windows pesquise por "Editar as variáveis de ambiente do sistema” e clique no primeiro resultado:
    Barra de busca do Windows.
    Figura 4. Barra de busca do Windows.
  2. Na janela que abrir, clique no botão “Variáveis de Ambiente…”:
    Janela de propriedades do sistema no Windows 10.
    Figura 5. Janela de propriedades do sistema no Windows 10.
  3. No campo superior, chamado “Variáveis de usuário…”, clique na variável “Path” e, então, no botão “Editar”:
    Variáveis de ambiente do sistema.
    Figura 6. Variáveis de ambiente do sistema.
  4. Na janela que abrir encontraremos uma lista de diretórios. Clique em “Novo” e adicione o endereço do diretório C:/src/flutter/bin do SDKe clique em “OK”:
    Caminho do Flutter SDK adicionado a variável de ambiente Path.
    Figura 7. Caminho do Flutter SDK adicionado a variável de ambiente Path.
  5. Para verificar se o SDK foi instalado corretamente, abra uma sessão do CMD e execute o seguinte comando:
    
    flutter doctor

    Se tudo estiver instalado corretamente, deverá receber uma resposta similar a essa:

    
    Doctor summary (to see all details, run flutter doctor -v):
    [√] Flutter (Channel beta, v1.1.8, on Microsoft Windows 
    [versão 10.0.17134.590], locale pt-BR)
    [!] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
        ! Some Android licenses not accepted.  To resolve this, 
        run: flutter doctor --android-licenses
    [√] Android Studio (version 3.2)
    [√] VS Code (version 1.31.1)
    [!] Connected device
        ! No devices available

Pronto! Agora que já possuímos o SDK, estamos prontos para configurar nossa IDE. Nesse artigo utilizaremos o Visual Studio Code, mas se quiser também pode utilizar o Android Studio (basta ter memória RAM suficiente):

  1. Com o Visual Studio Code aberto, no menu lateral, selecione a aba “extensões”:
    Botão de extensões do Visual Studio Code
    Figura 8. Botão de extensões do Visual Studio Code
  2. No campo de busca, digite “Flutter”. O primeiro resultado da busca será o plugin oficial. Clique no pequeno botão “Install” verde. O plugin já contém tudo que precisamos para executar e debugar nosso código Dart.
    Plugin oficial do Flutter para Visual Studio Code.
    Figura 9. Plugin oficial do Flutter para Visual Studio Code

Pronto! Finalmente podemos criar nosso primeiro aplicativo em Flutter!

Criando um aplicativo com Flutter

Com o SDK instalado e adicionado à variável de ambiente “Path”, criar um novo projeto Flutter é extremamente simples. Para isso, no terminal do Windows, navegue até o diretório onde deseja iniciar o seu projeto e execute o seguinte comando:


flutter create meu_primeiro_app
O parâmetro meu_primeiro_app é o nome da nossa aplicação. Sinta-se livre para colocar o nome que quiser.

O Flutter ficará encarregado de criar todos os arquivos da nossa aplicação. Feito isso, ainda no terminal, navegue até o diretório que foi criado pelo CLI:

cd meu_primeiro_app

Para abrir o projeto no Visual Studio Code basta executar o comando:

code .

Executando o aplicativo Flutter em um Emulador Android

O Android Studio, além do Android SDK, também nos fornece um emulador Android que contém todas as suas versões. Dessa forma, podemos testar o comportamento do nosso aplicativo em diversos dispositivos, ao mesmo tempo que elimina a necessidade de conectarmos um dispositivo físico para realizar testes, embora essa opção ainda seja possível.

No Visual Studio Code, abra o arquivo lib/main.dart. Ele será o ponto de entrada do nosso aplicativo, ou seja, toda aplicação será iniciada através da função main no início do arquivo. Todo o código que você vê abaixo dessa função é o aplicativo que o Flutter oferece como exemplo. Por enquanto não realizaremos nenhuma modificação, apenas executaremos este aplicativo. Para isso, com o arquivo aberto, pressione:

CRTL + F5

No topo superior do Visual Studio Code abrirá uma pequena aba. Se você já possui emuladores configurados, eles devem aparecer nessa aba. Se não, basta selecionar a opção “Create New”:

Executando o emulador Android a partir do Visual Studio Code.
Figura 10. Executando o emulador Android a partir do Visual Studio Code.

O processo deve demorar alguns minutos, e você pode acompanhá-lo através da pequena aba aberta no canto inferior direito:

Processo de carregamento do emulador.
Figura 11. Processo de carregamento do emulador.

Ao final do processo, quando o emulador for automaticamente aberto, pode ser que seu aplicativo não seja executado. Dessa forma, no Visual Studio Code, pressionamos “CRTL + F5” novamente. Entretanto, como o emulador já estará aberto, não será necessário escolher nenhuma opção. O Flutter ficará responsável por iniciar a aplicação no emulador e emitir todos os eventos e erros através da aba “DEBUG CONSOLE” no rodapé do Visual Studio Code:

Debug Console do Flutter.
Figura 12. Debug Console do Flutter.

Nesse momento, no emulador, seu aplicativo já será executado:

Aplicativo padrão criado automaticamente pelo comando flutter create.
Figura 13. Aplicativo padrão criado automaticamente pelo comando flutter create.

E é isso ai! Você acabou de entrar no mundo do desenvolvimento multiplataforma nativo. Que tal darmos uma explorada no aplicativo de exemplo que foi criado?

Widgets! Explorando um aplicativo Flutter

Tudo no Flutter é um Widget. Seja uma página, um botão ou um texto. Sempre que quisermos exibir qualquer tipo de elemento para o usuário, usaremos Widgets.

O Flutter fornece diversos Widgets que são essenciais para o funcionamento da nossa aplicação. Por isso, no arquivo main.dart onde podemos encontrar todos os elementos do nosso aplicativo de exemplo, logo na primeira linha, encontramos a importação dos Widgets do Material Design:

import 'package:flutter/material.dart';

Mais abaixo encontramos o Widget superior da aplicação. É nele, chamado de MyApp, que seremos capazes de definir um esquema de cores padrão, bem como o título e a página inicial do nosso aplicativo. Perceba também que a função main, a “porta de entrada” cria uma instância desse Widget, iniciando o aplicativo:


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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
context é uma instância de BuildContext que serve para informar ao Widget em que lugar ele se encontra dentro da árvore de Widgets da aplicação.

Repare que na linha 9, no parâmetro primarySwatch do construtor da classe ThemeData, passamos o valor Colors.blue. A classe Colors é fornecida pelo Flutter Material, onde encontramos diversas cores comumente utilizadas pelo Material Design. Que tal mudarmos a cor primária do nosso aplicativo para vermelho?


ThemeData(
       primarySwatch: Colors.red,
),

É só salvar e, em um passe de mágica, o recurso de Hot Reload do Flutter modificará nosso aplicativo executado no emulador:

Aplicativo padrão pintado de vermelho.
Figura 14. Aplicativo padrão pintado de vermelho.

Mais abaixo encontraremos outras duas classes: MyHomePage e _MyHomePageState. Diferentemente do Widget superior da aplicação, que se tratava de um StatelessWidget (um Widget que não armazena dados), o Widget da nossa página inicial se trata de um StatefulWidget (um Widget que armazena dados e possui Lifecycle). Por isso possuímos duas classes: a primeira, chamada MyHomePage, conterá apenas os dados imutáveis do nosso Widget, ou seja, apenas os dados que forem passados como parâmetro para o Widget. É essa classe que instanciamos dentro do Widget MyApp para abrir a página inicial.


class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

A segunda classe, _MyHomePageState, é onde armazenamos os dados mutáveis do componente (estado) e implementamos o método build utilizado pelo Flutter para criar o Widget na tela do usuário:


class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), 
    );
  }
}

Perceba que é nesse Widget que encontramos todo o código da nossa aplicação responsável por exibir o contador e, ao clique do botão de incremento, realizamos a atualização dos dados. Agora que alteramos a cor do nosso aplicativo, que tal implementar mais uma funcionalidade? Apenas um botão de incremento não é suficiente, também precisamos decrementar!

Ainda na classe _MyHomePageState criaremos mais um método chamado _decrementCounter. Este método ficará responsável por decrementar o atributo _counter da nossa aplicação e por executar o método setState disponível em todo Widget do tipo Stateful:


...
void _decrementCounter() {
   setState(() {
     _counter--;
   });
 }
...

Por fim precisaremos, no atributo floatingActionButton do Widget Scaffold, adicionar mais um botão ao lado do botão de incremento. Faremos isso agrupando ambos os botões no Widget Row, também disponibilizado pelo Flutter:


floatingActionButton: Row(
    mainAxisAlignment: MainAxisAlignment.end,
    children: <Widget>[
      FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
      const SizedBox(
        width: 10.0,
      ),
      FloatingActionButton(
        onPressed: _decrementCounter,
        tooltip: 'Decrement',
        child: const Icon(Icons.remove),
      ),
    ],
),

Salve as alterações e agora conseguimos mudar a cor de tema da aplicação, adicionando uma nova funcionalidade em alguns poucos passos.

Aplicativo aperfeiçoado com decremento do contador.
Figura 15. Aplicativo aperfeiçoado com decremento do contador.

Veja abaixo o código completo utilizado neste artigo.


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  void _decrementCounter() {
   setState(() {
     _counter--;
   });
 }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
          const SizedBox(
            width: 10.0,
          ),
          FloatingActionButton(
            onPressed: _decrementCounter,
            tooltip: 'Decrement',
            child: const Icon(Icons.remove),
          ),
        ],
     ),
    );
  }
}

Além dos recursos apresentados aqui, o Flutter fornece centenas de Widgets, que agilizam muito o processo de desenvolvimento.