Skip to main content

· 2 min read

Hey 👋,

Hoje vou compartilhar com você um commit bem interessante do repositório do Flutter:

Implementing switch expressions in foundation/ and material/

Contém a implementação do "novo" switch da linuagem Dart em 2 pacotes importantíssimos do framework: foundation e o material. É interessante ver na prática como um novo recurso da linguagem agora integra os aplicativos que iremos criar.

O Dart vem evoluindo e se aperfeiçoando, trazendo funcionalidades já existentes em outras linguagens, tornando-a assim mais robusta e atrativa, especialmente para dessenvolvedores de plataforma nativas que contam com alguns recurso que só existem no Kotlin/Swift.

Lendo o código antes e depois podemos avaliar o quanto a legibilidade melhora.

Aqui está o código antigo:

switch (parameters['value']) {
case 'Brightness.light':
debugBrightnessOverride = ui.Brightness.light;
case 'Brightness.dark':
debugBrightnessOverride = ui.Brightness.dark;
default:
debugBrightnessOverride = null;
}

Aqui está o código novo:

debugBrightnessOverride = switch (parameters['value']) {
'Brightness.light' => ui.Brightness.light,
'Brightness.dark' => ui.Brightness.dark,
_ => null,
};

Este novo switch foi introduzido na versão 3.1, liberada em agosto de 2023. Ou seja, não é uma atualização tão nova assim, mas só agora ela está fazendo parte do Flutter. Deixo aqui o link para você conferir em detalhes: https://dart.dev/language/branches#switch-expressions

Espero que você tenha gosta e esta dica tenha sido útil. Dá uma conferida no link do commit, vale a pena!

· One min read

BLoC Banner

Gerenciamento de estado com Flutter é um tópico bem amplo e neste post vamos explorar (um pouco) sobre o tão conhecido BLoC!

BLoC e bloc_library não são a mesma coisa! É crucial entender que, apesar do nome, eles representam coisas diferentes.

O padrão BLoC é uma arquitetura que separa a lógica de negócios da interface do usuário.

O package bloc_library é uma implementação concreta desse padrão.

O pattern e o package são distintos.

O pattern foi apresentado pelo Google na DartConf em 2018. Foi a arquitetura escolhidas para compartilhar a lógica de negócio entre um aplicativo Flutter e uma aplicação AngularDart, utilizando Streams.

O package implementa esta arquitetura, abstraindo e facilitando a implementação do pattern. E deu tão certo que é um dos packages mais populares para gerenciamento de estado.

E é essencial reconhecer que o pattern em si é independente e pode ser implementado sem este package.

· 2 min read
Resumão:

Flutter é um framework não-opinativo.

Responsabilidade e discernimento na escolha.

Mantenha o mais simples possível

O Flutter é um framework não opinativo, ou seja, ele não impõe e não obriga sobre como funcionalidades devem ser implementadas.

Permite que os desenvolvedores usem a sua criatividade e experiência para encontrar soluções personalizadas para seus problemas, em vez de serem forçados a seguir um conjunto rígido de regras e convenções impostas pelo framework.

Isso significa que é possível escolher diferentes opções que resolvem o mesmo problema.

Consumir uma API REST, utilizando o package http, dio ou chopper ?.

Navegação utilizando APIs nativas ou packages como fluro, beamer ou go_router ?.

Armazenamento local, com sqflite, drift ou isar ?.

Cada uma das opções possuem prós e contras.

No gerenciamento de estado, a mesma coisa.

Sobram alternativas nativas: setState(), ChangeNotifier, InheritedWidget, StreamBuilder, etc.

E packages, como riverpod, flutter_bloc, provider, mobx, etc.

Mas qual o motivo então de discussões acaloradas sobre a "melhor" alternativa para gerenciamento de estado ?

O motivo é simples: não existe "bala de prata", ou seja, não existe a melhor opção. E sim, aquela opção que se encaixa melhor no seu projeto.

Cabe aos desenvolvedores a responsabilidade e o discernimento na escolha.

É natural que as pessoas discutam sobre como fazer isso da “melhor” maneira possível. E cada um vai defender a sua escolha em detrimento das outras.

Felizmente, o amadurecimento do Flutter e da comunidade contribuíram para que estas discussões tivessem cada vez menos importância. Mas ainda assim continua sendo um tópico “quente”.

O Flutter é um framework que oferece flexibilidade e liberdade de escolha em suas implementações.

E como mencionado anteriormente, não existe a “melhor” maneira. A escolha da opção de gerenciamento de estado ideal depende do projeto e do contexto em que está sendo usada.

E para finalizar e responder a pergunta deste post, aqui está a resposta:

  • Avalie se as alternativas nativas são suficientes
  • Se optar por packages, considere a complexidade do estado no aplicativo. Avalie a documentação e repositório. Avalie mais de um package.
  • Faça uma prova de conceito com a situação mais complexa possível.

Regra de ouro: mantenha o mais simples possível.

· 3 min read

Youtube

Para complementar este post, também há o vídeo no youtube.

Novidades

A versão 3 do Flutter foi apresentado no Google I/O de 2022.

O grande destaque desta nova versão é que o framework está com suporte estável para macOS e Linux, atingindo 6 plataformas diferentes à partir da mesma codebase.

Outras 3 funcionalidade que chamaram a atenção foram:

Material 3

A nova geracao do Material Design está progressivamente sendo implementada, trazendo um novo esquema de cores, melhorias na tipografia novos componentes e uma capacidade muito maior na personalizacão dos aplicativos. Acompanhe a issue e fique por dentro das atualizacões.

https://github.com/flutter/flutter/issues/91605


Firebase Crashlytics

Agora é possível acessar em tempo real os relatórios de "crash" (com stacktrace completo) do seu aplicativo, algo antes exclusivo aos apps nativos. Vale ressalver que este recurso do Firebase é gratuito.


Flutter Web

Utilizando a API ImageDecoder (nos browsers que oferecem suporte) a decodificaćão de imagens ficou 2x mais rápida. E a nova API do Flutter que controla o ciclo de vida de um aplicativo agora fornece um controle maior da inicializaćão. Confira os detalhes no link

https://docs.flutter.dev/development/platform-integration/web/initialization


Performance

Como de costume, toda atualizacão do traz consigo melhorias em performance e desta vez não foi diferente. Basta atualizar a versão e executar o seu aplicativo.


Casual Games Toolkit

Um outra novidade que deixou muita gente empolgada é o . Um conjunto recursos para criar jogos casuais utilizando Flutter.

https://flutter.dev/games


Dart 2.17

A nova versão da linguagem Dart foi anunciada, trazendo como grandes novidades:

Enums

Agora é possível adicionar propriedades/métodos à um Enum.

enum FlutterBootcamp {
kura('setState'),
libria('testes'),
civitas('firebase');

final String conteudo;

const FlutterBootcamp(this.conteudo);

String exibirConteudo() {
return 'O principal conteúdo deste app é: $conteudo';
}
}

void main() => print(FlutterBootcamp.civitas.exibirConteudo());

Super initializers

A passagem de parametro para "super-classe" (ou classe mãe) ficou mais simples:

class Bootcamp {
String? linguagem;
Bootcamp({this.linguagem});
...
}

// Antes
class FlutterBootcamp extends Bootcamp {
FlutterBootcamp({String? linguagem}) : super(linguagem: linguagem);
}

// Depois
class FlutterBootcamp extends Bootcamp {
FlutterBootcamp({super.linguagem});
}

Named args

Os named arguments podem ser informados em qualquer ordem. Não precisam ser declarados no final do construtor.

class FlutterBootcamp {
final String? conteudo;
final int? aplicativos;

const FlutterBootcamp(this.conteudo, {this.aplicativos});
}

// antes
FlutterBootcamp('Do básico ao avançado', aplicativos: 6);

// depois
FlutterBootcamp(aplicativos: 6, 'Do básico ao avançado');

· 2 min read

Neste post, vamos explorar um dos conceitos mais importantes para quem está começando com Flutter: o ciclo de vida dos widgets.

Voçe já deve saber que em Flutter, tudo é um widget e que temos 2 tipos: Stateless e o Stateful.

E a diferença entre eles é o objeto State, pois ele confere ao Stateful o poder da mutação enquanto o Stateless permanece imutável.

O construtor destes widgets tem a mesma estrutura:

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


Widget build(BuildContext context) {
return Container(color: const Color(0xFF2DBD3A));
}
}
class YellowBird extends StatefulWidget {
const YellowBird({ Key? key }) : super(key: key);


State<YellowBird> createState() => _YellowBirdState();
}

Ambos aos serem implementados, fazem override diferentes: método build no Stateless e o Stateful faz do createState(), nos obrigando à implementar _YellowBirdState().

E nele nós temos o seguinte código:

class _YellowBirdState extends State<YellowBird> {

Widget build(BuildContext context) {
return Container(color: const Color(0xFFFFE306));
}
}

E é aqui que a mágica acontece. Graças ao objeto State, podemos mudar a cor do Container de amarelo para vermelha, usando o setState(). Algo impossível de se fazer em no GreenFrog, que possui a cor verde e por ser um Stateless widget, é imutável.

Até aqui deduzimos então que:

tip

Stateless e Stateful widgets possuem o mesmo ciclo de vida. Quando o construtor é invocado, eles executam o mesmo override.

E como vimos anteriormente, o Stateful possui o override ao método createState() e que o retorno é um objeto State.

E é exatamente aqui que aprofundamos quando se trata do “ciclo de vida dos widgets”.

Sendo bem rigorosos, podemos afirmar que o “ciclo de vida”, portanto, trata-se do objeto State e não do Stateless/Stateful.

Sendo menos rigorosos, podemos afirmar que o “ciclo de vida” de um Stateful é mais amplo, pois envolve também o objeto State, afinal, não é possível criar um Stateful sem ter um objeto State.

No próximo post, iremos abordar os métodos o initState e o dispose, pois são eles que acompanham a criação e destruição do objeto State (do Stateful widget).

· 3 min read
Resumão:

Imperativa: especificar como resolver um problema; controle detalhado.

Declarativa: concentra-se no que o código deve realizar; concentrar no resultado.

Essas duas abordagens são comumente usadas na programação e é importante entender suas diferenças para compreender melhor o uso declarativo pelo Flutter.

Compreender a diferença, facilita o entendimento em como o Flutter constroi interfaces.

Imperativa

É um processo passo a passo que diz ao computador o que fazer e como fazê-lo. Em outras palavras, é um conjunto de instruções que o computador segue para alcançar o resultado desejado.

A programação imperativa envolve escrever código que especifique exatamente como resolver um problema. Ela é baseada no controle do fluxo de execução usando declarações como loops, condicionais e variáveis. Lembre-se: passo-a-passo.

Adequada para situações em que você precisa ter mais controle sobre o fluxo do programa. Isso significa que se você precisa fazer algo muito específico e precisa ter certeza de que é feito de uma maneira determinada, então a abordagem imperativa pode ser a melhor.

Declarativa

É baseada em descrever o resultado desejado sem especificar como alcançá-lo. Em vez de escrever código que especifica como resolver um problema, a programação declarativa se concentra no que o código deve realizar.

A programação declarativa envolve escrever código que descreve o problema e o resultado desejado, sem especificar como chegar lá. É baseado na definição de regras e relacionamentos entre elementos. Lembre-se: resultado-desejado.

Adequada para situações em que você deseja descrever o que deseja alcançar, sem se preocupar em como chegar lá. Isso significa que se você deseja se concentrar no resultado, e não no processo.

Ao trabalhar com interfaces de usuário, usar a abordagem declarativa para garantir que a interface pareça e se comporte exatamente como você deseja, sem se preocupar com a forma como é implementada.

Na prática

SQL: Declarativo. Declaramos o resultado ao banco de dados: inserir, atualizar, excluir, consultar... mas nós não o instruimos em como ele deve executar tais operações.

Algorítimo: Imperativo. Imposto a cada linha de código como ele deve se comportar. Declarar variável, computar valores, avaliar expressões. Estamos instruindo exatamente o comportamento que queremos que o programa tenha.

Flutter

Como mecionado anteriormente, o Flutter utiliza a abordagem declarativa: resultado.

Ao construi interfaces com ele, declaramos algo como: 1 imagem, 2 campos de texto e um botão.

E o framework se encarrega de todo o resto, sem se preocupar com a implementação de cada elemento.

Com isso, os desenvolvedores podem se concentrar no que desejam alcançar e deixar que o framework se encarregue de como implementá-lo.

Até breve

· One min read

Depois de 3 anos e quase 130 commits, esta é a nova versão do site. Muita coisa mudou no Flutterverse, mas o desejo em continuar compartilhando conteúdo de qualidade para a comunidade continuam iguais.

Assim como o Flutter evoluiu, o flutterparainiciantes.com.br também não poderia ficar para trás.

Conteúdo revisado && atualizado. O site está muito mais completo.

E agora tem um blog.

Tudo para deixar o seu aprendizado mais fácil.

Até mais ✌️