我有两个有状态的小部件,第一个名为MyApp,它在ListView构建器中显示员工列表。第二个有状态小部件名为ActionButton,它也是一个有状态的小部件。
ActionButton小部件返回一个Alert Dialog。在"警报"对话框中,我可以通过输入员工姓名和薪资来添加新员工。
问题是,为了显示新添加的员工,我必须热重新加载应用程序。有没有办法通知MyApp小部件已经添加了新员工,然后在ListView生成器中显示新添加的员工。
以下是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代码:
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);
}
}
谢谢你的帮助。致以最诚挚的问候
看看这个。颤振状态管理
目前有三种管理状态的方法: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);
}
}
用法:
- 在EmployeeProvider中包装整个应用程序(或感兴趣的部分(
每当需要更新列表时
EmployeeProvider.of(context).listChange.add(NewEmployeeList);
在StreamBuilder 中包装需要重新绘制的小部件
StreamBuilder<List<Employee>>( stream: EmployeeProvider.of(context).list, builder: (context, snapshot)=>ListView( children: snapshot.data.map(mapDataToListTile), ), );
每当流接收到新值时,StreamBuilder中的小部件就会立即重新绘制。