Context Extension
Você já usou Context Extensions ou conhecia essa maneira de trabalhar com elas?
Introdução
Muitos devs buscam ter uma maior produtividade durante o tempo de desenvolvimento, e buscar trazer atalhos é sempre muito útil. Quando se trabalha em um grande projeto então, nem se fala. Quanto mais recursos e funcionalidades houverem, sabendo medir o ponto e os requisitos do projeto, melhor.
E com uso de extensions, não é diferente. Pois elas podem ajudar bastante, tornando o uso dos nossos objetos mais poderosos.
Então vamos a alguns casos de uso e exemplos práticos.
Exemplos
Você certamente já fez algo do tipo:
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.blue,
),
Mas, para ficar um pouco mais limpo, criou uma variável e a utilizou.
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;Container(
width: size.width,
height: size.height,
color: Colors.blue,
),
Isso é muito bom, pois de certa forma traz maior clareza, além de tornar o seu código mais fácil e consiso de se ler.
Mas você pode ir além, utilizando extensions para isso.
No caso, criar uma extension:
import 'package:flutter/material.dart';extension MediaQueryExt on BuildContext {
double get height => MediaQuery.of(this).size.height;
double get width => MediaQuery.of(this).size.width;
}
E usar na aplicação — precisando somente fazer o import.
Usando, dessa maneira:
import 'package:context_ext/extensions/context_extension.dart';Container(
width: context.width,
height: context.height,
color: Colors.blue,
),
Aqui, você está usando o context para utilizar os dois objetos criados (ou melhor, extendidos do BuildContext).
— Além disso, lembre-se de sempre fazer o import.
Essa técnica, não tão conhecida é realmente muito útil.
Isso é só um pequeno exemplo, mas já imaginou utilizar extensions com várias outras implementações no context? Isso é possível!
Se liga em alguns exemplos abaixo!
Indo ao próximo nível
Agora é hora de vermos ainda mais formas de implementá-las.
Confira a seguir:
- Navigator
- Antes
onPressed: () => Navigator.of(context).pushNamed(‘/’),
- Depois
— Você cria a extension
extension NavigatorExt on BuildContext {
Future<T?> pushNamed<T>(String routeName, {Object? arguments}) =>
Navigator.pushNamed<T?>(this, routeName, arguments: arguments);
}
— E utiliza
onPressed: () => context.pushNamed('/'),
- Theme
- Antes
style: Theme.of(context).textTheme.headline5,
- Depois
— Você cria a extension
extension ThemeExt on BuildContext {
TextTheme get textTheme => Theme.of(this).textTheme;
}
— E utiliza
style: context.textTheme.headline5,
- Scaffold
- Antes
onPressed: () => Scaffold.of(context).openDrawer(),
- Depois
— Você cria a extension
extension ScaffoldExt on BuildContext {
void openDrawer() => Scaffold.of(this).openDrawer();
}
— E utiliza
onPressed: () => context.openDrawer(),
- FocusScope
- Antes
onPressed: () =>
FocusScope.of(context).requestFocus(specificFocusNode);
- Depois
— Você cria a extension
extension FocusScopeExt on BuildContext {
FocusScopeContext get focusScope => FocusScopeContext(this);
}
— E utiliza
onPressed: () => context.focusScope.requestFocus(specificFocusNode);
💡 Sobre as extensions
Nos casos acima, estamos dando o foco nas possibilidades com o BuildContext. Mas é importante lembrar que é possível criar extensions para qualquer tipo em Dart. Para mais informações, leia mais aqui.
Veja o exemplo abaixo, onde criamos criando uma extesion de int e utilizando no Duration:
- Duration
- Antes
InkWell(
onTap: () => Future.delayed(
const Duration(milliseconds: 16),
() => ...
),
child: Text(''),
),
— Você cria a extension
extension IntSC on int {
Duration get milliseconds {
return Duration(milliseconds: this);
}
}
— E utiliza
InkWell(
onTap: () => Future.delayed(
16.milliseconds,
() => ...
),
child: Text(''),
),
Utilizando e turbinando suas extensions
Muito massa esse recurso né? E olha que você só experimentou uma parte.
Agora pra turbinar ainda mais, você pode dar uma olhada no projeto abaixo com várias context extensions para aplicar nos seus projetos — que estão no arquivo context_extension
.
E assim, entender ainda melhor o funcionamento e criação na prática.
Hoje há no pub.dev o pacote build_context, que traz alguns desses exemplos, mas você pode facilmente exportar o arquivo context_extension
do projeto acima - que inclusive há alguns incrementos -, copiar para o seu projeto e usá-lo. Pois concorda comigo que é mais fácil e simples você fazer isso (copiá-lo para o seu projeto), do que depender de um package para isso?
Além disso, arquiteturalmente, eu sugeriria para que você adicione em uma estrutura parecida com a abaixo:
├── 📦 lib
│ ├─ 📂 commons
│ │ ├─ 📂 extensions
│ │ │ ├─ 📜 context_extension.dart
Dessa forma, você adiciona uma camada que pode ser compartilhada nas demais features e implementações do seu projeto.
Mas claro, você pode adaptar com base nas suas necessidades do seu projeto e à arquitetura que o mesmo segue hoje.
— Afinal, uma única e simples feature não precisa mudar a forma com que você trabalha hoje no seu projeto.
Lembrando que quaisquer sugestões para incrementar são e serão super bem vindas. Além de possíveis adaptações também.
Considerações Finais
E aí, curtiram conhecer esse recurso? Aposto que sim!
Se tiverem alguma dúvida ou feedback a respeito do conteúdo, pode mandar nos comentários.
Além disso, se esse artigo te ajudou de alguma forma, dá o 👏 para fortalecer e garantir que esse conteúdo chegará em mais pessoas.
Valeu e vamos pra cima, em busca do próximo nível! 🏆