我正在使用提供程序Flutter 包。
我有一个主列表,主列表的每个项目都有一个子列表。我可以将项目添加到主列表并且它正在工作,但每次我向子列表添加项目时,用户界面都不会更新。运行代码并添加一些项目并打开它们,然后在其中添加一些项目(这是子列表),您将看到您不会看到任何更新,但如果您最小化键盘,UI 将得到更新。也许因为我用来Provider.of<Collection>(context)访问子列表和notifyListeners()类的对象CityName无法运行,findById(id)这就是我能想到的。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Collection(),
),
ChangeNotifierProvider.value(
value: CityName(),
)
],
child: MaterialApp(
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _textEditingController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ListView(
children: Provider.of<Collection>(context)
.cityNameCollection
.map((collection) {
return CollectionCard(collection.title, collection.id);
}).toList()),
),
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: _textEditingController,
autofocus: true,
),
),
FlatButton(
onPressed: () {
Provider.of<Collection>(context)
.addCollection(_textEditingController.text);
_textEditingController.clear();
},
child: Text(
'ADD',
),
),
],
),
),
]),
);
}
}
class CollectionCard extends StatelessWidget {
final String title;
final String id;
CollectionCard(this.title, this.id);
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 20),
child: Text(title),
),
),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => CityNamesList(id),
),
);
},
);
}
}
class CityNamesList extends StatelessWidget {
final String id;
CityNamesList(this.id);
final _textEditingController = TextEditingController();
@override
Widget build(BuildContext context) {
final item = Provider.of<Collection>(context).findById(id);
return Scaffold(
appBar: AppBar(
title: Text(item.title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ListView(
children: item.names.map((name) {
return ListTile(
title: Text(name),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
item.removeName(name);
},
),
);
}).toList()),
),
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: _textEditingController,
autofocus: true,
),
),
FlatButton(
onPressed: () {
item.addName(_textEditingController.text);
_textEditingController.clear();
},
child: Text(
'ADD',
),
),
],
),
),
],
),
);
}
}
class Collection with ChangeNotifier {
List<CityName> cityNameCollection = [];
void addCollection(value) {
cityNameCollection
.add(CityName(title: value, id: DateTime.now().toString()));
notifyListeners();
}
CityName findById(id) {
return cityNameCollection.firstWhere((a) => a.id == id);
}
}
class CityName with ChangeNotifier {
String title;
String id;
List<String> names = [];
CityName({this.title, this.id});
void addName(value) {
names.add(value);
notifyListeners();
}
void removeName(value) {
names.remove(value);
notifyListeners();
}
}
Run Code Online (Sandbox Code Playgroud)
这里有几个问题
1)您正在Collection()内部创建ChangeNotifierProvider.value,这可能会导致重新创建它(不仅是现在,而且在代码发生一些更改之后)。相反,使用ChangeNotifierProviderwithbuilder只会创建一次值
2)您使用的是单个 ChangeNotifierProviderfor CityName,而可以有多个CityName实例。因此,不会引用CityName所有提供者的特定实例,而是始终为您提供相同的实例
3)传递collection.id然后通过id查找是没有必要的,并且会使代码变得复杂。只需传递集合实例本身
4)CityNamesList没有具体提供CityName,而是从提供商处获取Collection。在这种情况下,UI 将不会被重建,因为它不监听CityNamesList更改。实际上它监听Collection变化,但Collection 不知道它的项目何时变化,因为没有人notifyListeners() 调用Collection内部CityName@addName
5)最后,CityName的构造函数字段是可选的(不是必需的),它允许创建虚拟实例并导致错误
这是一个如何解决此问题的示例(removeName为了简单起见,没有)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
builder: (context) => Collection(),
child: MaterialApp(
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _textEditingController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ListView(
children: Provider.of<Collection>(context)
.cityNameCollection
.map((item) => CollectionCard(item))
.toList(),
),
),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: _textEditingController,
autofocus: true,
),
),
FlatButton(
onPressed: () {
Provider.of<Collection>(context)
.addCollection(_textEditingController.text);
_textEditingController.clear();
},
child: Text('ADD'),
),
],
),
],
),
);
}
}
class CollectionCard extends StatelessWidget {
final CityName item;
CollectionCard(this.item);
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
child: Text(item.title),
),
),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return ChangeNotifierProvider.value(
value: item,
child: CityNamesList(),
);
},
),
);
},
);
}
}
class CityNamesList extends StatelessWidget {
final _textEditingController = TextEditingController();
@override
Widget build(BuildContext context) {
final item = Provider.of<CityName>(context);
return Scaffold(
appBar: AppBar(
title: Text(item.title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ListView(
children: item.names.map((name) {
return ListTile(
title: Text(name),
);
}).toList(),
),
),
Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: _textEditingController,
autofocus: true,
),
),
FlatButton(
onPressed: () {
item.addName(_textEditingController.text);
_textEditingController.clear();
},
child: Text('ADD'),
),
],
),
),
],
),
);
}
}
class Collection with ChangeNotifier {
List<CityName> cityNameCollection = [];
void addCollection(String value) {
cityNameCollection.add(CityName(title: value));
notifyListeners();
}
}
class CityName with ChangeNotifier {
String title;
List<String> names = [];
CityName({@required this.title});
void addName(value) {
names.add(value);
notifyListeners();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14557 次 |
| 最近记录: |