为什么我的列表在重新排列项目后没有重建
Why my list is not rebuild after rearanging items
这是使用 Flutter 和 Provider 包的玩具应用。我的目标很简单:
- OuterProvider
有用于构建列表的数据 (ListView.builder
)
- Outer provider
有 Shuffle
按钮可以随机播放内部列表
- 内部小部件 (Rows
) 使用 InnerProvider
随机更改数据
当我点击 InnerWidget
- 提供商正确更新数据
但是当我洗牌数据时,即使数据被洗牌了。构建方法是 运行 但我的小部件列表不受影响......
这里是示例代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'dart:math';
class InnerProvider extends ChangeNotifier {
int pid;
InnerProvider(this.pid);
get id => pid;
set id(int i) {
pid = i;
notifyListeners();
}
}
class OuterProvider extends ChangeNotifier {
List _data = [
InnerProvider(1),
InnerProvider(3),
InnerProvider(4),
InnerProvider(5),
];
get data => _data;
addToData(var item) {
data.add(item);
notifyListeners();
}
reShuffle() {
data.shuffle();
notifyListeners();
}
changeId(var i) {
var dtIndex = _data.indexOf(i);
_data[dtIndex].id = Random().nextInt(99);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<OuterProvider>(
create: (_) => OuterProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Why this does not work?'),
));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List outerData;
void reShuffleData() {
Provider.of<OuterProvider>(context).reShuffle();
}
@override
Widget build(BuildContext context) {
outerData = Provider.of<OuterProvider>(context, listen: true).data;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView.builder(
itemCount: outerData.length,
itemBuilder: (context, int i) {
return ChangeNotifierProvider<InnerProvider>(
create: (_) => outerData[i], child: InnerChild());
})),
floatingActionButton: FloatingActionButton(
onPressed: reShuffleData,
tooltip: 'Shuffle',
child: Icon(Icons.add),
),
);
}
}
class InnerChild extends StatelessWidget {
Widget build(BuildContext context) {
var prov = Provider.of<InnerProvider>(context);
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
GestureDetector(
onTap: () {
Provider.of<OuterProvider>(context).changeId(prov);
},
child: Text(
Provider.of<InnerProvider>(context).id.toString(),
style: TextStyle(fontSize: 40),
)),
]);
}
}
以下是工作代码。您正在使用默认值并且没有使用更改。请参考下面的代码。
已编辑
对于此用例,您应该使用 ChangeNotifierProvider.value
而不是 ChangeNotifierProvider
。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'dart:math';
class InnerProvider extends ChangeNotifier {
int pid;
InnerProvider(this.pid);
get id => pid;
set id(int i) {
pid = i;
notifyListeners();
}
}
class OuterProvider extends ChangeNotifier {
List _data = [
InnerProvider(1),
InnerProvider(3),
InnerProvider(4),
InnerProvider(5),
];
get data => _data;
addToData(var item) {
data.add(item);
notifyListeners();
}
reShuffle() {
data.shuffle();
notifyListeners();
}
changeId(var i) {
var dtIndex = _data.indexOf(i);
_data[dtIndex].id = Random().nextInt(99);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<OuterProvider>(
create: (_) => OuterProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Why this does not work?'),
));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List outerData;
void reShuffleData() {
Provider.of<OuterProvider>(context).reShuffle();
}
@override
Widget build(BuildContext context) {
outerData = Provider.of<OuterProvider>(context, listen: true).data;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView.builder(
itemCount: outerData.length,
itemBuilder: (context, int i) {
return ChangeNotifierProvider<InnerProvider>.value(
value: outerData[i],
child: InnerChild(),
);
})),
floatingActionButton: FloatingActionButton(
onPressed: reShuffleData,
tooltip: 'Shuffle',
child: Icon(Icons.add),
),
);
}
}
class InnerChild extends StatelessWidget {
Widget build(BuildContext context) {
var prov = Provider.of<InnerProvider>(context);
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
GestureDetector(
onTap: () {
Provider.of<OuterProvider>(context).changeId(prov);
},
child: Text(
Provider.of<InnerProvider>(context).id.toString(),
style: TextStyle(fontSize: 40),
)),
]);
}
}
这是使用 Flutter 和 Provider 包的玩具应用。我的目标很简单:
- OuterProvider
有用于构建列表的数据 (ListView.builder
)
- Outer provider
有 Shuffle
按钮可以随机播放内部列表
- 内部小部件 (Rows
) 使用 InnerProvider
随机更改数据
当我点击 InnerWidget
- 提供商正确更新数据
但是当我洗牌数据时,即使数据被洗牌了。构建方法是 运行 但我的小部件列表不受影响......
这里是示例代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'dart:math';
class InnerProvider extends ChangeNotifier {
int pid;
InnerProvider(this.pid);
get id => pid;
set id(int i) {
pid = i;
notifyListeners();
}
}
class OuterProvider extends ChangeNotifier {
List _data = [
InnerProvider(1),
InnerProvider(3),
InnerProvider(4),
InnerProvider(5),
];
get data => _data;
addToData(var item) {
data.add(item);
notifyListeners();
}
reShuffle() {
data.shuffle();
notifyListeners();
}
changeId(var i) {
var dtIndex = _data.indexOf(i);
_data[dtIndex].id = Random().nextInt(99);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<OuterProvider>(
create: (_) => OuterProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Why this does not work?'),
));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List outerData;
void reShuffleData() {
Provider.of<OuterProvider>(context).reShuffle();
}
@override
Widget build(BuildContext context) {
outerData = Provider.of<OuterProvider>(context, listen: true).data;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView.builder(
itemCount: outerData.length,
itemBuilder: (context, int i) {
return ChangeNotifierProvider<InnerProvider>(
create: (_) => outerData[i], child: InnerChild());
})),
floatingActionButton: FloatingActionButton(
onPressed: reShuffleData,
tooltip: 'Shuffle',
child: Icon(Icons.add),
),
);
}
}
class InnerChild extends StatelessWidget {
Widget build(BuildContext context) {
var prov = Provider.of<InnerProvider>(context);
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
GestureDetector(
onTap: () {
Provider.of<OuterProvider>(context).changeId(prov);
},
child: Text(
Provider.of<InnerProvider>(context).id.toString(),
style: TextStyle(fontSize: 40),
)),
]);
}
}
以下是工作代码。您正在使用默认值并且没有使用更改。请参考下面的代码。
已编辑
对于此用例,您应该使用 ChangeNotifierProvider.value
而不是 ChangeNotifierProvider
。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'dart:math';
class InnerProvider extends ChangeNotifier {
int pid;
InnerProvider(this.pid);
get id => pid;
set id(int i) {
pid = i;
notifyListeners();
}
}
class OuterProvider extends ChangeNotifier {
List _data = [
InnerProvider(1),
InnerProvider(3),
InnerProvider(4),
InnerProvider(5),
];
get data => _data;
addToData(var item) {
data.add(item);
notifyListeners();
}
reShuffle() {
data.shuffle();
notifyListeners();
}
changeId(var i) {
var dtIndex = _data.indexOf(i);
_data[dtIndex].id = Random().nextInt(99);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<OuterProvider>(
create: (_) => OuterProvider(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Why this does not work?'),
));
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List outerData;
void reShuffleData() {
Provider.of<OuterProvider>(context).reShuffle();
}
@override
Widget build(BuildContext context) {
outerData = Provider.of<OuterProvider>(context, listen: true).data;
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView.builder(
itemCount: outerData.length,
itemBuilder: (context, int i) {
return ChangeNotifierProvider<InnerProvider>.value(
value: outerData[i],
child: InnerChild(),
);
})),
floatingActionButton: FloatingActionButton(
onPressed: reShuffleData,
tooltip: 'Shuffle',
child: Icon(Icons.add),
),
);
}
}
class InnerChild extends StatelessWidget {
Widget build(BuildContext context) {
var prov = Provider.of<InnerProvider>(context);
return Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
GestureDetector(
onTap: () {
Provider.of<OuterProvider>(context).changeId(prov);
},
child: Text(
Provider.of<InnerProvider>(context).id.toString(),
style: TextStyle(fontSize: 40),
)),
]);
}
}