Percebi que é possível criar widgets usando funções simples em vez de criar uma subclasse de StatelessWidget . Um exemplo seria este:
Widget function({ String title, VoidCallback callback }) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
Isso é interessante porque requer muito menos código do que uma classe completa. Exemplo:
class SomeWidget extends StatelessWidget {
final VoidCallback callback;
final String title;
const SomeWidget({Key key, this.callback, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: callback,
child: // some widget
);
}
}
Então, estive me perguntando: Existe alguma diferença além da sintaxe entre funções e classes para criar widgets? E é uma boa prática usar funções?
Respostas:
TL; DR: Prefira o uso de classes em vez de funções para tornar a árvore de widget reutilizável .
EDITAR : Para compensar alguns mal-entendidos: Não se trata de funções que causam problemas, mas de classes que resolvem alguns.
Flutter não teria StatelessWidget se uma função pudesse fazer a mesma coisa.
Da mesma forma, é direcionado principalmente para widgets públicos, feitos para serem reutilizados. Não importa tanto para funções privadas feitas para serem usadas apenas uma vez - embora estar ciente desse comportamento ainda seja bom.
Há uma diferença importante entre usar funções em vez de classes, ou seja: O framework não tem conhecimento das funções, mas pode ver as classes.
Considere a seguinte função de "widget":
usado desta forma:
E é equivalente a classe:
usado assim:
No papel, ambos parecem fazer exatamente a mesma coisa: criar 2
Container
, com um aninhado no outro. Mas a realidade é um pouco diferente.No caso de funções, a árvore de widgets gerada é semelhante a esta:
Enquanto com classes, a árvore do widget é:
Isso é importante porque muda como a estrutura se comporta ao atualizar um widget.
Por que isso importa
Ao usar funções para dividir sua árvore de widgets em vários widgets, você se expõe a bugs e perde algumas otimizações de desempenho.
Não há garantia de que você terá bugs usando funções, mas usando classes, você tem a garantia de não enfrentar esses problemas.
Aqui estão alguns exemplos interativos no Dartpad que você pode executar para entender melhor os problemas:
https://dartpad.dev/1870e726d7e04699bc8f9d78ba71da35
Este exemplo mostra como, ao dividir seu aplicativo em funções, você pode acidentalmente quebrar coisas como
AnimatedSwitcher
https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
Este exemplo mostra como as classes permitem reconstruções mais granulares da árvore de widgets, melhorando o desempenho
https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
Este exemplo mostra como, ao usar funções, você se expõe ao uso incorreto de BuildContext e enfrenta bugs ao usar InheritedWidgets (como Tema ou provedores)
Conclusão
Aqui está uma lista selecionada das diferenças entre o uso de funções e classes:
showDialogs
& semelhantes)ClassWidget
na árvore de widgets mostrada pelo devtool, que ajuda a entender o que está na telaSe ocorrer uma exceção (como ProviderNotFound), a estrutura fornecerá o nome do widget atualmente em construção. Se você dividiu sua árvore de widgets apenas em funções +
Builder
, seus erros não terão um nome útilNo geral, é considerado uma prática ruim usar funções em vez de classes para reutilizar widgets por esses motivos.
Você pode , mas pode morder você no futuro.
fonte
Tenho pesquisado sobre esse problema nos últimos 2 dias. Cheguei à seguinte conclusão: tudo bem dividir partes do aplicativo em funções. É ideal que essas funções retornem um
StatelessWidget
, então otimizações podem ser feitas, como fazer oStatelessWidget
const
, para que ele não reconstrua se não for necessário. Por exemplo, este trecho de código é perfeitamente válido:O uso de função ali está perfeitamente bem, pois retorna a
const StatelessWidget
. Por favor me corrija se eu estiver errado.fonte
const
na frente da classe apátrida para todos os casos? Ou tem que ser certos casos? Se sim, quais são eles?const
todos os lugares. Por exemplo, se você tem umaStatelessWidget
classe que retorna umText
contendo o valor de uma variável, e essa variável muda em algum lugar, então vocêStatelessWidget
deve ser reconstruído, para que possa mostrar aquele valor diferente, portanto, não pode serconst
. Acho que a forma segura de colocar é a seguinte: onde puder, useconst
, se for seguro fazê-lo.Havia uma grande diferença entre o que as funções fazem e o que a classe faz.
Vamos explicar do zero.🙂 (apenas sobre o imperativo)
Todos nós sabemos que a história da programação começou com comandos básicos diretos (por exemplo: Montagem).
Em seguida, a programação estruturada veio com controles de fluxo (por exemplo: if, switch, while, for etc). Este paradigma permite aos programadores controlar o fluxo do programa de forma eficaz e também minimizar o número de linhas de código por loops.
Em seguida, veio a programação de procedimentos, que agrupa as instruções em procedimentos (funções). Isso deu dois grandes benefícios para os programadores.
1. Agrupe as instruções (operações) em blocos separados.
2. É possível reutilizar esses blocos. (Funções)
Mas, acima de tudo, os paradigmas não deram uma solução para o gerenciamento de aplicativos. A programação de procedimentos também pode ser usada apenas para aplicativos de pequena escala. Isso não pode ser usado para desenvolver grandes aplicativos da web (por exemplo: banking, google, youtube, facebook, stackoverflow etc), não pode criar estruturas como android sdk, flutter sdk e muito mais ......
Assim, os engenheiros pesquisam muito mais para gerenciar os programas de maneira adequada.
Finalmente, a Programação Orientada a Objetos vem com todas as soluções para gerenciar aplicativos em qualquer escala (de hello world a Trilhões de pessoas usando a criação de sistemas, por exemplo, google, amazon e hoje 90% dos aplicativos).
Em oop, todos os aplicativos são construídos em torno de Objetos. Significa que o aplicativo é uma coleção desses objetos.
portanto, os objetos são a construção básica para qualquer aplicativo.
classe (objeto em tempo de execução) agrupa dados e funções relacionadas a essas variáveis (dados). assim, o objeto compõe os dados e suas operações relacionadas.
[Aqui, não vou explicar sobre oop]
👉👉👉 Ok, agora vamos para a estrutura de flutter.👈👈👈
-Dart suporta procedimentos e oop Mas, o framework Flutter é completamente construído usando classes (oop). (Porque grande estrutura gerenciável não pode criar usando procedural)
Aqui, vou criar uma lista de razões pelas quais eles usam classes em vez de funções para fazer widgets.👇👇👇
1 - Na maioria das vezes, o método de construção (widget filho) chama o número de funções síncronas e assíncronas.
Ex:
portanto, o método de construção precisa ser mantido em um widget de classe separado (porque todos os outros métodos chamados pelo método build () podem ser mantidos em uma classe)
2 - Usando a classe widget, você pode criar o número de outra classe sem escrever o mesmo código repetidas vezes (** Use Of Inheritance ** (extends)).
E também usando herança (estender) e polimorfismo (substituir), você pode criar sua própria classe personalizada. (Abaixo o exemplo, lá eu irei personalizar (Substituir) a animação estendendo MaterialPageRoute (porque sua transição padrão eu quero personalizar) .👇
3 - Funções não podem adicionar condições para seus parâmetros, mas usando o construtor do widget de classe, você pode fazer isso.
Abaixo, exemplo de código👇 (este recurso é muito usado por widgets de framework)
4 - As funções não podem usar const e o widget Class pode usar const para seus construtores. (que afetam o desempenho do tópico principal)
5 - Você pode criar qualquer número de widgets independentes usando a mesma classe (instâncias de uma classe / objetos). Mas a função não pode criar widgets independentes (instância), mas a reutilização pode.
[cada instância tem sua própria variável de instância e que é completamente independente de outros widgets (objeto), mas a variável local da função depende de cada chamada de função * (o que significa que, quando você altera um valor de uma variável local, ela afeta todas as outras partes do o aplicativo que usa esta função)]
Havia muitas vantagens na aula em relação às funções. (Acima, apenas alguns casos de uso)
🤯 Meu pensamento final
Portanto, não use funções como bloco de construção de seu aplicativo, use-as apenas para fazer operações. Caso contrário, ele causará muitos problemas impossíveis de lidar quando seu aplicativo se tornar escalável .
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
VOCÊ NÃO PODE MEDIR A QUALIDADE DO PROGRAMA POR NÚMERO DE DECLARAÇÕES (ou linhas) USO POR ELE
📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍📍 📍📍📍📍📍📍📍
Obrigado pela leitura
fonte
shrinkHelper() { return const SizedBox.shrink(); }
é o mesmo que usarconst SizedBox.shrink()
embutido em sua árvore de widgets e, usando funções auxiliares, você pode limitar a quantidade de aninhamento em um só lugar.Ao chamar o widget Flutter, certifique-se de usar a palavra-chave const. Por exemplo
const MyListWidget();
fonte
const
palavra - chave ao chamar o widget sem estado refatorado, ele deve ser chamado apenas uma vez.