在窗口小部件之间颤动传递数据? [英] Flutter pass data between widgets?
问题描述
我有两个有状态的小部件,第一个名为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);
}
}
用法:
- 将整个应用(或感兴趣的部分)包装在EmployeeProvider中
-
每当需要更新列表时
- Wrap the entire app (or interested part) in a EmployeeProvider
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屋!