在窗口小部件之间颤动传递数据? [英] Flutter pass data between widgets?

查看:95
本文介绍了在窗口小部件之间颤动传递数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个有状态的小部件,第一个名为MyApp,可显示ListView构建器中的雇员列表.第二个有状态的小部件名为ActionButton,它也是一个有状态的小部件.

I have two stateful widgets, the first one titled as MyApp which displays the list of employees in a ListView builder. The second stateful widget is titled ActionButton which is also a statefull widget.

ActionButton小部件将返回一个警报"对话框.在警报"对话框中,我可以通过输入员工姓名和薪水来添加新员工.

The ActionButton widget returns an Alert Dialog. In the Alert Dialog I can add a new employee by entering the employee Name and Salary.

问题是,为了显示新添加的员工,我必须热重新加载应用程序.有没有一种方法可以通知MyApp小部件已经添加了新的Employee,然后在ListView构建器中显示新添加的雇员.

The issue is, in order to show the newly added employee I have to hot reload the application. Is there a way to inform MyApp widget that a new Employee has been added, and then display the new added employee in the ListView builder.

下面是MyApp窗口小部件的代码:

Below is the code for MyApp Widget:

                  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代码:

Last but not least, ActionButton code:

    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);
      }
    }

感谢您的帮助. 最好的问候

Thank you for your help. Best Regards

推荐答案

检查一下. 颤振状态管理

当前有三种管理状态的方法:SetState(),InheritedWidget和BLoC.

There are currently three ways to manage a state: SetState(), InheritedWidget and BLoC.

根据我的经验,如果您想要重绘一个小部件,则BLoC是最好的.这是最简单的方法.

From my experience, if you what you want is a widget redraw, BLoC is the best. It's the most straightforward method.

定义BLoC和提供者:

Defining the BLoC and Provider:

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. 每当需要更新列表时

  1. Wrap the entire app (or interested part) in a EmployeeProvider
  2. Whenever need to update the list

EmployeeProvider.of(context).listChange.add(NewEmployeeList);

  • 包装需要在StreamBuilder中重绘的小部件

  • Wrap the widget that needs to be redrawn in a StreamBuilder

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

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

    只要流收到新值,StreamBuilder中的小部件就会立即重绘.

    Whenever the stream received a new value, the widget inside the StreamBuilder immediately redraws.

    这篇关于在窗口小部件之间颤动传递数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆