#statelesswidget
🚨 Avoid unnecessary StatefulWidgets!

Using a `StatelessWidget` where appropriate leads to more compact, concise, and readable code and is more idiomatic.

Learn more: dcm.dev/docs/rules/f...

#FlutterDev #Dart #Flutter
November 18, 2024 at 6:27 PM
Did you know?

When you call MediaQuery.of(context) inside a build method, the widget will rebuild when any of the MediaQuery properties change.

But there's a better way that lets you depend only on the properties you care about (and minimize unnecessary rebuilds). 👇
November 8, 2024 at 2:29 PM
I just published The Widget That Never Changes — And Why That’s Its Superpower medium.com/p/the-widget...
#Flutter #MobileDevelopment #Android #iOS #Dart
The Widget That Never Changes — And Why That’s Its Superpower
StatelessWidget is the foundation of every Flutter app. Once you truly understand it, the rest of Flutter starts to make sense.
medium.com
May 22, 2026 at 1:15 AM
Did you know?

In Flutter, you can easily create a responsive split-view widget that works on mobile, desktop and web.

You can do this in 30 lines of code, without any 3rd party packages: 👇
February 10, 2025 at 4:18 PM
Fun fuckt: this is the boilerplate to instantiate an empty component that does not return any state yet in Flutter. If you change something in this, the framework will implode of cringe
February 7, 2024 at 3:49 PM
Man learnt flutter for 2 hours today.

Got familiar with the widgets, first creating the StatelessWidget, then with the MaterialApp then Scaffold. Trying to get my head around all of it.

So practicing as I'm going along to solidify my understanding.

But, so far having fun!
#learning #flutter
January 29, 2025 at 7:50 PM
Why install 3rd-party packages for Flutter infinite scroll?
With BlocSignal mixins, your ScrollController *is* your state machine:
• 100% StatelessWidget UI
• Streamless droppable() concurrency
• Clean ScrollPosition.extentAfter
dev.to/gde/taming-f...
Taming Flutter Infinite Scroll (Part 2): Turning ScrollController into a Reactive State Machine with CubitSignalMixin
Discover how to eliminate Flutter StatefulWidget boilerplate and overcome Dart's single-inheritance wall by combining ScrollController with CubitSignalMixin and BlocSignalMixin for a 100% StatelessWid...
dev.to
September 3, 2026 at 5:40 PM
Interesting that a non-const StatelessWidget has no performance benefits against helper functions. But still, like you said in your forum post, the benefits of StatelessWidgets still outweigh the use of helper functions
February 1, 2025 at 8:12 AM
🚀 Widgets Métodos vs Clases Statefulwidget/statelesswidget en #Flutter, ¿Cuál es Mejor?

🚀 Hablo sobre que debemos de emplear al momento de desarrolar widgets personalizados más complejos en Flutter.

youtu.be/nU6Qm7iPeSQ
🚀 Widgets Métodos vs Clases Statefulwidget/statelesswidget en Flutter, ¿Cuál es Mejor?
YouTube video by Andrés Cruz
youtu.be
May 2, 2025 at 4:58 PM
🚀 #Widgets Métodos vs Clases Statefulwidget/statelesswidget en #Flutter, ¿Cuál es Mejor?

🚀 Hablo sobre que debemos de emplear al momento de desarrolar widgets personalizados más complejos en Flutter.

Video:

youtu.be/nU6Qm7iPeSQ

Publicación:

www.desarrollolibre.net/blog/flutter...
May 2, 2025 at 2:30 PM
Começando com testes no Flutter
## O básico O melhor lugar para começarmos é pelo básico, e um dos melhores exemplos para quem começou a aprender a desenvolver em Flutter é o projeto inicial, o famoso **CounterApp** , que é um projeto simples contendo apenas um botão de “+” e um contador que incrementamos ao pressionar o botão. Assim que criamos um projeto temos a seguinte estrutura de código no nosso arquivo `main.dart`: void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } 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.headlineMedium, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } Então podemos prosseguir e analisar como podemos montar nossos testes para essa tela, e o projeto já nos dá uma breve introdução aos testes de widget por meio de arquivo `test/widget_test.dart`: void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. await tester.pumpWidget(const MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); // Tap the '+' icon and trigger a frame. await tester.tap(find.byIcon(Icons.add)); await tester.pump(); // Verify that our counter has incremented. expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); }); } Esse é um teste bem simples, ele tem o único objetivo de verificar se ao pressionar o botão "+” o contador na tela é incrementado, mas como ele faz isso é o que vamos ver. ## Como executar os testes Antes de tudo para executarmos todos os testes que se encontram na pasta /test do nosso projeto basta executarmos o seguinte comando no terminal na pasta do projeto: flutter test Para executarmos apenas um arquivo de teste específico basta adicionar o caminho e nome do arquivo ao final: flutter test test/widget_test.dart ## main() void main() { .. } A primeira coisa que conseguimos notar é que da mesma forma que nossa aplicação, nosso teste também é iniciado dentro de uma função `main()` , mas diferente da aplicação ele consegue identificar que é um teste simplesmente pelo nome do arquivo, então os arquivos que possuem **test** ao final do nome são considerados arquivos de teste, por isso ele não vai exigir um aparelho ou emulador para fazer a execução. Da mesma forma se não nomearmos nosso arquivo de teste da maneira correta ele vai tentar executar nossos testes como uma aplicação, e claro esse não é o comportamento que esperamos. ## testWidgets() testWidgets('Counter increments smoke test', (WidgetTester tester) async { ... }); Para iniciar um teste precisamos de um bloco de código com a única responsabilidade de executar nosso cenário especifico, e essa é a função do `testWidgets()` . E para que ela funcione precisamos de dois parâmetros: `description` : a descrição do teste, por meio dele podemos esclarecer o que nosso teste faz. `callback` : recebe o bloco de teste que será executado, sendo possível executar código assíncronos utilizando `async/await` . Essa função foi criada para testar widgets, mas se no caso você deseja fazer apenas um teste unitário você pode usar a função `test()` que tem a mesma assinatura mas não tem acesso ao `WidgetTester` . test('Counter increments smoke test', () { ... }); ## tester.pumpWidget() await tester.pumpWidget(const MyApp()); Essa é a função responsável por renderizar a UI do Widget recebido para o teste, ela vai fazer a chamada da função `runApp()` da mesma forma que é feita no arquivo `main.dart` para iniciar nossa aplicação. Por isso é necessário que o widget informado seja um `MaterialApp`. Nesse cenário o teste vai funcionar normalmente, mas se precisamos testar outro widget que não possui o `MaterialApp` no início da árvore precisamos adicioná-lo. await tester.pumpWidget(MaterialApp(home: const MySecondPage())); ## expect() expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); Essa função é o ponto vital do nosso teste, ela que é responsável por dizer se nosso teste foi um sucesso ou uma falha. Se o valor esperado for igual ao valor recebido o teste é um sucesso. Para isso recebemos dois parâmetros, o primeiro é o valor ou variável que queremos verificar e o segundo é a condição que desejamos atender. > Se estiver comparando dois objetos com instâncias diferentes é necessário fazer o override da função == e do campo hasCode do objeto para considerar os valores dos campos ao invés da instância. Dessa forma podemos ler a primeira chamada do `expect` da seguinte forma: > Eu espero que esse campo (`find.text('0')`) possua esse valor (`findsOneWidget`) **Mas o que significam esses campos?** A variável `find` é um objeto próprio da biblioteca de teste do flutter que nos permite ter acesso a várias funções que podemos usar para encontrarmos nossos widgets na tela, como por exemplo: > ancestor(...) > byElementPredicate(...) > byElementType(...) > byIcon(...) > byKey(...) > byType(...) > byWidget(...) Em meio a quantidade de métodos podemos ficar perdidos sobre qual usar, mas o ideal aqui é sempre tentar encontrar o widget que queremos da forma mais simples possível, e é isso que é feito no teste de exemplo. Ao declarar `find.text('0')` ele deseja encontrar qualquer widget na tela que possua um texto com o valor ‘0’, esse é o valor inicial do nosso contador ao iniciar a tela. O campo `findsOneWidget` é o nosso **matcher** , ele é responsável por responder se existe pelo menos 1 widget com o valor que declaramos. E podemos usar outras variações, como por exemplo: * `findsNothing` - espera que o finder não encontre nada * `findsWidgets` - espera que o finder encontre um ou mais widgets * `findsNWidgets` - espera que o finder encontre uma quantidade específica de widgets que nós informamos * `findsAtLeastNWidgets` - espera que o finder encontre pelo menos uma quantidade mínima de widgets que nós informamos Agora ao voltarmos ao exemplo inicial podemos entender o seguinte: expect(find.text('0'), findsOneWidget); > Espero que seja encontrado apenas um widget com o texto '0' > expect(find.text('1'), findsNothing); > Espero que não seja encontrado nenhum um widget com o texto '1' ## tester.tap() await tester.tap(find.byIcon(Icons.add)); A função `tester.tap()` tem um nome bem sugestivo, em casos onde queremos acionar o gesto de pressionar de algum widget é ele que faz isso. Nesse teste por exemplo ele primeiro vai usar o **finder** para encontrar algum widget que usa o ícone `Icons.add` , e ao encontrar, ele vai acionar o `tap` ou pressioná-lo. Após isso esperamos então que a nossa tela seja atualizada modificando o valor de "0” pra "1”, e não queremos encontrar o texto "0” e sim "1”. expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); Mas se executarmos nosso teste assim teremos um erro porque nossa função **tap** realizou uma mudança de estado na tela mas nosso widget não foi atualizado. Vamos ver como resolver isso com a função `tester.pump()`. ## tester.pump() await tester.pump(); Quando executamos um teste de widget ele é renderizado e os testes são executados em cima do frame inicial da tela, mas quando temos uma mudança de estado no nosso widget nosso teste precisa saber disso, e essa função faz isso, diz ao teste que o estado do widget precisa ser atualizado para o próximo frame. Nesse exemplo, após pressionarmos o botão de "+” esperamos que o frame da tela seja atualizado para que o texto "0” seja substituído por "1”, então precisamos chamar essa função para que ele entenda que precisa fazer isso. await tester.pump(); Também podemos passar para função uma duração se quisermos que a atualização seja feita após algum período. await tester.pump(Duration(seconds: 5)); Ou podemos usar o `pumpAndSettle()` que vai esperar pelo próximo frame para continuar o teste. await tester.pumpAndSettle(); Agora se executarmos o teste novamente ele vai ser concluído com sucesso. void main() { testWidgets('Deve verificar se o contador está sendo incrementado', (WidgetTester tester) async { // Renderiza nosso widget await tester.pumpWidget(const MyApp()); // Verifica se o contador é iniciado no 0. expect(find.text('0'), findsOneWidget); expect(find.text('1'), findsNothing); // Pressiona o botão '+' para incrementar o contador e atualiza a tela await tester.tap(find.byIcon(Icons.add)); await tester.pump(); // Verifica se o contador foi incrementado expect(find.text('0'), findsNothing); expect(find.text('1'), findsOneWidget); }); } ## Conclusão Conseguimos por meio desses testes garantir que a tela da nossa aplicação funcione da maneira correta e assim podemos evitar que caso sejam adicionados mais recursos, essa funcionalidade continue funcionando como o esperado.
forem.com
March 12, 2025 at 10:15 PM
v0.0.15 of xmplus_survey_sdk survey sdk for flutter power by xmplus Changelog excerpt: - **HYSurveyView 重构**:从 StatelessWidget 改为 StatefulWidget,参数全部改为 final 并支持 con...

Origin | Interest | Match
v0.0.15 of xmplus_survey_sdk
survey sdk for flutter power by xmplus Changelog excerpt: - **HYSurveyView 重构**:从 StatelessWidget 改为 StatefulWidget,参数全部改为 final 并支持 const 构造 - **键盘性能优化**:HySurveyWidget 新增 widget 树缓存,避免键盘动画每帧重建整个视图 - 修复 `android/build.gradle`中 `task clean`旧语法 - 新增 Sliver 瀑布流模式的示例页面
pub.dev
May 6, 2026 at 5:25 AM
💚 "Add `submenuIcon` property to override the default `SubmenuButton` arrow icon" [flutter/flutter#160086]
opened by @tahatesser.com is waiting for review ✨
Add `submenuIcon` property to override the default `SubmenuButton` arrow icon
Fixes #132898 Code sample expand to view the code sample import &#39;package:flutter/material.dart&#39;; void main() =&gt; runApp(const MyApp()); class MyApp extends StatelessWidget { const M...
github.com
December 11, 2024 at 11:50 AM