Флаттер передает данные между виджетами?

У меня есть два виджета с состоянием, первый под названием MyApp, который отображает список сотрудников в построителе ListView. Второй виджет с состоянием называется ActionButton, который также является виджетом с полным состоянием.

Виджет ActionButton возвращает диалог оповещения. В диалоге оповещения я могу добавить нового сотрудника, введя имя сотрудника и зарплату.

Проблема в том, чтобы показать вновь добавленного сотрудника, мне нужно перезагрузить приложение. Есть ли способ сообщить виджету MyApp, что добавлен новый сотрудник, а затем отобразить нового добавленного сотрудника в построителе ListView.

Ниже приведен код для виджета MyApp:

                  import 'package:flutter/material.dart';

            import './database_helper.dart';
            import './floating_action_button.dart';

            void main() async {
              DatabaseHelper databaseHelper = new DatabaseHelper();
              List employees = [];
              employees = await databaseHelper.getAllEmployees();

              runApp(MyApp(employees));
            }

            class MyApp extends StatefulWidget {
              final List employees;

              MyApp(this.employees);

              @override
              _MyAppState createState() => _MyAppState();
            }

            class _MyAppState extends State<MyApp> {
              List employees = [];

              @override
              void initState() {
                super.initState();
                employees = widget.employees;
              }

              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  home: Scaffold(
                    appBar: AppBar(
                      title: Text("Employees"),
                    ),
                    body: Container(
                      child: ListView.builder(
                        itemCount: employees.length,
                        itemBuilder: (BuildContext context, int index) {
                          return new Card(
                            child: ListTile(
                              title: Text(employees[index]["empName"]),
                              subtitle: Text(
                                employees[index]["empSalary"].toString()),
                              trailing: RaisedButton(
                                onPressed: () {
                                  removeEmployee(
                                     employees[index]["id"], index);
                                },
                                child: Icon(
                                  Icons.remove,
                                  color: Colors.white,
                                ),
                                shape: CircleBorder(),
                                color: Theme.of(context).primaryColor,
                              ),
                            ),
                          );
                        },
                      ),
                    ),
                    floatingActionButton: ActionButton(),
                  ),
                );
              }

              Future<int> removeEmployee(int id, int index) async {
                DatabaseHelper databaseHelper = new DatabaseHelper();
                var result = await databaseHelper.deleteEmployee(id);
                if (result == 1) {
                  setState(() {
                    employees.removeAt(index);
                  });
                }
                return result;
              }
            }

И последнее, но не менее важное, код ActionButton:

    import 'package:employees/database_helper.dart';
    import 'package:employees/employee.dart';
    import 'package:flutter/material.dart';

    class ActionButton extends StatefulWidget {
      @override
      _ActionButtonState createState() => _ActionButtonState();
    }

    class _ActionButtonState extends State<ActionButton> {
      var _employeeNameController = new TextEditingController();
      var _employeeSalaryController = new TextEditingController();

      @override
      Widget build(BuildContext context) {
        return FloatingActionButton(
          child: Icon(
            Icons.add,
            color: Colors.white,
          ),
          onPressed: () {
            showDialog(
              context: context,
              builder: (_) {
                return AlertDialog(
                  title: Text("Add New Employees"),
                  content: Column(
                    children: <Widget>[
                      TextField(
                        controller: _employeeNameController,
                      ),
                      TextField(
                        controller: _employeeSalaryController,
                      ),
                    ],
                  ),
                  actions: <Widget>[
                    RaisedButton(
                      onPressed: () {
                        setState(
                          () {
                            addNewEmployee();
                          },
                        );
                      },
                      child: Text("Add Employee"),
                    ),
                  ],
                );
              },
            );
          },
        );
      }

      void addNewEmployee() async {
        DatabaseHelper databaseHelper = new DatabaseHelper();
        Employee employee = new Employee(
              _employeeNameController.text,
              int.parse(_employeeSalaryController.text));
        await databaseHelper.insertEmployee(employee);
      }
    }

Спасибо за помощь. С уважением

1 ответ

Проверь это. Флаттер Государственное управление

В настоящее время существует три способа управления состоянием: SetState(), InheritedWidget и BLoC.

Из моего опыта, если вы хотите, чтобы вы перерисовали виджет, BLoC - лучший. Это самый простой метод.

Определение BLoC и провайдера:

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:rxdart/rxdart.dart';

class EmployeeProvider extends InheritedWidget {
  final employeeBloc=EmployeeBloc();
  EmployeeProvider({Key key, @required Widget child,})
      : assert(child != null),
        super(key: key, child: child);

  static EmployeeBloc of(BuildContext context) {
    return (context.inheritFromWidgetOfExactType(EmployeeProvider) as EmployeeProvider).employeeBloc;
  }

  @override
  bool updateShouldNotify(EmployeeProvider old)=>true;
}

class EmployeeBloc{
  //This is the output interface of Bloc
  ValueObservable<List<Employee>> get list => _list.stream;//seedValue: '/'
  final _list = BehaviorSubject<List<Employee>>();//seedValue: '/'

  // This is the input interface of Bloc
  Sink<List<Employee>> get listChange => _listChangeController.sink;
  final _listChangeController = StreamController<List<Employee>>();

  EmployeeBloc(){
    _listChangeController.stream.listen(_handleListChange);
  }
  // This is the logic handling input
  void _handleListChange(List<Employee> newList){
    _list.add(newList);
  }
}

Использование:

  1. Оберните все приложение (или заинтересованную часть) в EmployeeProvider
  2. Всякий раз, когда нужно обновить список

    EmployeeProvider.of(context).listChange.add(NewEmployeeList);
    
  3. Оберните виджет, который должен быть перерисован в StreamBuilder

    StreamBuilder<List<Employee>>( stream: EmployeeProvider.of(context).list, builder: (context, snapshot)=>ListView( children: snapshot.data.map(mapDataToListTile), ), );

Всякий раз, когда поток получает новое значение, виджет внутри StreamBuilder немедленно перерисовывается.

Другие вопросы по тегам