1
resposta

[Sugestão] Forma alternativa para aplicar o TaskInherited

Eu recorri a esse meio pois seguindo os passos do vídeo não obtive sucesso; a nova tarefa não aparecia, apesar de adicionada à lista de tarefas. Baseando-me num artigo de InheritedWidget indicado pelo curso anterior, adotei as seguintes medidas e funcionou:

Primeiro, o atributo tasks virou um parâmetro obrigatório, a fim de que ele seja repassado na criação das respectivas árvores de Widget.

class TaskInherited extends InheritedWidget {
  static final List<TaskCard> defaultTasks = [...];
  final List<TaskCard> tasks;

  const TaskInherited({super.key, required this.tasks, required super.child});

  static TaskInherited of(BuildContext context) {...}

  @override
  bool updateShouldNotify(TaskInherited old) {...}

  addTask(String name, String photo, int difficulty) {...}
}

Segundo, o MaterialApp cria a tela inicial, carregando as tarefas-padrão criadas anteriormente no TaskInherited.

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MyApp',
      theme: customTheme,
      home: TaskInherited(
        tasks: TaskInherited.defaultTasks,
        child: const TaskScreen(),
      ),
    );
  }
}

Terceiro, na navegação para tela de formulário utilizo o pushReplacement a fim de repor uma nova tela, e repassando a lista de tarefas do contexto atual a um novo TaskInherited e uma nova árvore de Widgets.

...
class _TaskScreenState extends State<TaskScreen> {
  ...

  onFloatingActionButtonPressed() =>
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(
          builder:
              (context) =>
              TaskInherited(tasks: TaskInherited
                  .of(this.context)
                  .tasks, child: const TaskFormScreen()),
        ),
      );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: ...,
      body: ...,
      floatingActionButton: FloatingActionButton(
        heroTag: "addTaskButton",
        onPressed: onFloatingActionButtonPressed,
        child: Icon(Icons.add),
      ),
    );
  }
}

Por fim, estabeleço todas as ligações à tela anterior utilizando também o pushReplacement, pois preciso recriar a árvore de Widgets instanciando um novo TaskInherited, e também repassando a mesma lista de tarefas do contexto. Adiciona-se uma tarefa através do mesmo contexto.

class _TaskFormScreenState extends State<TaskFormScreen> {
  ...

  onFormButtonPressed() {
    ...
    TaskInherited.of(context).addTask(
      _nameController.text,
      _imageController.text,
      int.parse(_difficultyController.text),
    );
    ...
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder:
            (context) => TaskInherited(
              tasks: TaskInherited.of(this.context).tasks,
              child: const TaskScreen(),
            ),
      ),
    );
  }

  onAppBarButtonPressed() => Navigator.pushReplacement(
    context,
    MaterialPageRoute(
      builder:
          (context) => TaskInherited(
            tasks: TaskInherited.of(this.context).tasks,
            child: TaskScreen(),
          ),
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          onPressed: onAppBarButtonPressed,
          ...
        ),
        ...
      ),
      body: Form(
        key: _taskFormKey,
        child: Center(
          child: SingleChildScrollView(
            child: Container(
              ...
              child: Column(
                ...
                children: [
                  ...
                  Padding(
                    ...
                    child: FilledButton(
                      onPressed: onFormButtonPressed,
                      ...
                      ),
                      ...
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
1 resposta

Oi Ian!

Que bom que você encontrou uma solução alternativa que funcionou para o seu caso! O uso do InheritedWidget pode ser um pouco desafiador, mas é uma poderosa ferramenta para gerenciar o estado em aplicações Flutter.

A sua abordagem de fazer o TaskInherited receber a lista de tarefas como um parâmetro obrigatório e recriar a árvore de widgets com pushReplacement resolveu o problema e e ela tbm garante que o estado atualizado seja propagado corretamente para os widgets filhos.

Mandou muito bem, grato por compartilhar, tenho certeza que pode ajudar outras pessoas.

Bons estudos!

Sucesso