Skip to content

Instantly share code, notes, and snippets.

@felipecastrosales
Created October 27, 2022 00:41
Show Gist options
  • Save felipecastrosales/81da339ec17ded9f150d899e866dcb6a to your computer and use it in GitHub Desktop.
Save felipecastrosales/81da339ec17ded9f150d899e866dcb6a to your computer and use it in GitHub Desktop.
context_ext

Context Extension

Untitled

❓ Você já usou Context Extensions ou conhecia essa maneira de trabalhar com elas?

Isso representa muito o uso dessa extension que você verá no artigo! 😂

Isso representa muito o uso dessa extension que você verá no artigo! 😂


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 {
  Size get mediaQuerySize => MediaQuery.of(this).size;
  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,
),

Essa técnica, não tão conhecida - e que eu também não conhecia -, é 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:

  • Para 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('/'),
  • Em 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,
  • No 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](https://dart.dev/guides/language/extension-methods).
  • Veja o exemplo abaixo, onde criamos criando extensions de int e utilizando no Duration:
    • Antes:

      InkWell(
        onTap: () => Future.delayed(
          const Duration(milliseconds: 16),
          () => ...
        ),
        child: Text(''),
      ),
    • Depois:

      • Você cria:

        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 extensions de contexto para aplicar nos seus projetos - que estão no arquivo context_extension. E assim, entender ainda melhor o funcionamento e criação.

💬 Irei adicionar o repositório abaixo. 👇

felipecastrosales - Repositories

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

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; que a forja é diária! 🏆


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment