从一个屏幕跳转到另一个屏幕时,如何不丢失列表中的数据?
How to not lose a data from the list when going from one screen to another screen in flutter?
我有一个扩展 ChangeNotifier 的 class ViewTotalItemProvider
。在class里面,有一个这样的列表。
class ViewTotalItemProvider extends ChangeNotifier{
List<CartPlantLists> cartPlantList3 = [];
}
此外,还有3个屏幕,包括class喜欢,PlantFeatureScreen1
,ParticularPlant2
,CartDetais3
。所有都是有状态的小部件,我在第二个屏幕中添加了一些项目,即 ParticularPlant2
class。
当我尝试在第二个屏幕和第三个屏幕中显示列表中的项目时,它起作用了。
但该值未在 firstScreen 中更新,即 PlantFeatureScreen1
。但是,当我重新加载应用程序时,它会显示更新后的值。
为什么会这样?我该如何解决?
代码
ViewTotalItemProvider
List<CartPlantLists> cartPlantList3 = [];
class ViewTotalItemProvider extends ChangeNotifier{
addQuantity(index){
cartPlantList3[index].qu++;
notifyListeners();
}
subtrachQuantity(index){
cartPlantList3[index].qu--;
notifyListeners();
}
}
firstScreen PlantFeatureScreen1
(这里我想更新最后一个小部件中的值)
class PlantFeatureScreen1 extends StatefulWidget {
@override
_PlantFeatureScreen1State createState() => _PlantFeatureScreen1State();
}
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ViewTotalItemProvider>(
create: (context) => ViewTotalItemProvider(),
child:Builder(builder: (context) {
return Column(
children: <Widget>[
TopAppBar(),
Expanded(
flex: 1,
child: Align(
alignment: Alignment(-1, 0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
),
child: Text(
"Plants",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w700),
),
),
),
),
Expanded(
flex: 5,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.blue,
),
child: DefaultTabController(
length: 5,
child: Column(
children: [
Container(
height: 50,
width: double.infinity,
child: TabBar(
isScrollable: true,
tabs: ourAllLists.tabMaker(),
),
),
Container(
height: 317,
width: double.infinity,
decoration: BoxDecoration(color: Colors.white),
child: TabBarView(
children: ourAllLists.tabViewerMaker(context),),),
],
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Container(
alignment: Alignment.bottomRight,
height: 120,
width: double.infinity,
child: Stack(
overflow: Overflow.visible,
children: [
Container(
height: 70,
width: 105,
decoration: BoxDecoration(
color: Color(0xFF96CA2D),
borderRadius: BorderRadiusDirectional.horizontal(
end: Radius.circular(32),
start: Radius.circular(32))),
child: Icon(FontAwesomeIcons.shoppingBag,color:Colors.white,size:30),
),
Positioned(
// top: 0,
bottom: 50,
right: 0,
child: Consumer<ViewTotalItemProvider>(
builder: (context, value, child){
return Container(
height: 35,
width: 35,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50),
border: Border.all(color: Color(0xFF96CA2D),width: 4)
),
child: Center(child: Text(ourAllLists.totalquantity().toString(),style:TextStyle(fontSize: 20,color: Color(0xFF96CA2D)))),
);
}),
),
],
),
),
)
],
);
})
);
}
}
secondScreen ParticularPlant2
class ParticularPlant2 extends StatefulWidget {
final indexNumber;
ParticularPlant2({@required this.indexNumber});
@override
_ParticularPlant2State createState() => _ParticularPlant2State();
}
class _ParticularPlant2State extends State<ParticularPlant2> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TopAppBar(),
Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadiusDirectional.only(
bottomStart: Radius.circular(50),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber].pN,
style: kPlantNameStyle,
),
Text(
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber].ca
.toUpperCase(),
style: TextStyle(
fontSize: 15,
),
),
Text(
"$" +
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber]
.pr
.toString(),
style: kItemPrice,
),
SizedBox(height: 100),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50)),
child: Icon(
FontAwesomeIcons.flag,
color: Color(0xFF9DCD3C),
),
),
SizedBox(
height: 50,
),
FlatButton(
onPressed: () {
final tile = cartPlantList3.firstWhere(
(item) =>
item.pN ==
ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pN,
orElse: () => null);
if (tile != null) {
} else {
cartPlantList3.add(
CartPlantLists(
quantity: 1,
plantName: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pN,
category: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.ca,
price: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pr,
),
);
}
print(cartPlantList3.length);
},
child: Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: Color(0xFF9DCD3C),
borderRadius: BorderRadius.circular(50)),
child: Icon(FontAwesomeIcons.shoppingBag,
color: Colors.white),
),
)
],
),
Container(
height: 250,
child: Image(image: AssetImage("assets/tulip.png")),
)
],
)
],
),
)
],
),
),
),
);
}
}
看来您使用 Provider 的方式不对。在您的场景中执行此操作的最佳方法是使用 MultiProvider 将 MaterialApp 包装在 main.dart 文件中的 MyApp() 中。尝试这样的事情:https://pub.dev/packages/provider#multiprovider 你可以在其中放置一个 ChangeNotifierProvider。
return MultiProvider(
providers: [
ChangeNotifierProvider<ViewTotalItemProvider>(
create: (context) => ViewTotalItemProvider()),
],
child: MaterialApp(...)
);
此外,您必须在模型中放置 getter 和 setter。这是一个例子:
class ImageModel extends ChangeNotifier {
String _base64Image;
get base64Image => _base64Image;
set base64Image(String base64Image) {
_base64Image = base64Image;
notifyListeners();
}
}
我还建议使用 Selector 而不是 Consumer(理想情况下,您应该使用 Selector 而不是 Consumer,以便小部件仅在其监听的值发生变化时才重建)这是一个基于上述模型的示例:
@override
Widget build(BuildContext context) {
//other widgets
Selector<ImageModel, String>(
selector: (_, model) => model.base64Image,
builder: (_, image, __) {
return Text(image);
},
);
}
)
}
以下是使用 RaisedButton 获取和设置它的方法:
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
final itemModel;
List<CartPlantLists> myList=[];
@override
Widget build(BuildContext context) {
itemModel = Provider.of<ViewTotalItemProvider>(context,listen:false);
print(itemModel.yourVariable); //getting the value
return Container(
child: RaisedButton(
child:Text("Set Item");
onPressed:(){
itemModel.yourVariable=myList; //setting the value
},
),
);
}
}
希望对您有所帮助!祝你好运!
第一步:
在 pubspec.yaml 文件
中添加对提供者模式的依赖
dependencies:
flutter:
sdk: flutter
provider: ^4.1.2
第 2 步:
在单独的文件中创建提供程序:
class ViewTotalItemProvider with ChangeNotifier{
List<CartPlantLists> _cartPlantList1 = [];
get cartPlantList1 => _cartPlantList1 ;
set cartPlantList1 (List<CartPlantLists> selected){
_cartPlantList1 = selected;
notifyListeners();
}
}
第 3 步:
使用 MultiProvider 将 MaterialApp 小部件包装在 main.dart.
中
void main() => runApp(
MultiProvider (providers: [
ChangeNotifierProvider<ViewTotalItemProvider>.value(value:
ViewTotalItemProvider()),
],
child: MyApp()
)
);
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
第 4 步:
在屏幕中使用提供程序 PlantFeatureScreen1 :
class PlantFeatureScreen1 extends StatefulWidget {
@override
_PlantFeatureScreen1State createState() => _PlantFeatureScreen1State();
}
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
var viewTotalItemProvider;
@override
Widget build(BuildContext context) {
viewTotalItemProvider = Provider.of<ViewTotalItemProvider>(context);
return Scaffold(
.......
);
}
}
第 5 步:
获取 cartPlantList1.
List<CartPlantLists> list = viewTotalItemProvider.cartPlantList1;
第 6 步:设置 cartPlantList1。
List<CartPlantLists> list = [];
...
viewTotalItemProvider.cartPlantList1 = list;
类似地,你可以用于其他两个 类。
我有一个扩展 ChangeNotifier 的 class ViewTotalItemProvider
。在class里面,有一个这样的列表。
class ViewTotalItemProvider extends ChangeNotifier{
List<CartPlantLists> cartPlantList3 = [];
}
此外,还有3个屏幕,包括class喜欢,PlantFeatureScreen1
,ParticularPlant2
,CartDetais3
。所有都是有状态的小部件,我在第二个屏幕中添加了一些项目,即 ParticularPlant2
class。
当我尝试在第二个屏幕和第三个屏幕中显示列表中的项目时,它起作用了。
但该值未在 firstScreen 中更新,即 PlantFeatureScreen1
。但是,当我重新加载应用程序时,它会显示更新后的值。
为什么会这样?我该如何解决?
代码
ViewTotalItemProvider
List<CartPlantLists> cartPlantList3 = [];
class ViewTotalItemProvider extends ChangeNotifier{
addQuantity(index){
cartPlantList3[index].qu++;
notifyListeners();
}
subtrachQuantity(index){
cartPlantList3[index].qu--;
notifyListeners();
}
}
firstScreen PlantFeatureScreen1
(这里我想更新最后一个小部件中的值)
class PlantFeatureScreen1 extends StatefulWidget {
@override
_PlantFeatureScreen1State createState() => _PlantFeatureScreen1State();
}
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<ViewTotalItemProvider>(
create: (context) => ViewTotalItemProvider(),
child:Builder(builder: (context) {
return Column(
children: <Widget>[
TopAppBar(),
Expanded(
flex: 1,
child: Align(
alignment: Alignment(-1, 0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
),
child: Text(
"Plants",
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w700),
),
),
),
),
Expanded(
flex: 5,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.blue,
),
child: DefaultTabController(
length: 5,
child: Column(
children: [
Container(
height: 50,
width: double.infinity,
child: TabBar(
isScrollable: true,
tabs: ourAllLists.tabMaker(),
),
),
Container(
height: 317,
width: double.infinity,
decoration: BoxDecoration(color: Colors.white),
child: TabBarView(
children: ourAllLists.tabViewerMaker(context),),),
],
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Container(
alignment: Alignment.bottomRight,
height: 120,
width: double.infinity,
child: Stack(
overflow: Overflow.visible,
children: [
Container(
height: 70,
width: 105,
decoration: BoxDecoration(
color: Color(0xFF96CA2D),
borderRadius: BorderRadiusDirectional.horizontal(
end: Radius.circular(32),
start: Radius.circular(32))),
child: Icon(FontAwesomeIcons.shoppingBag,color:Colors.white,size:30),
),
Positioned(
// top: 0,
bottom: 50,
right: 0,
child: Consumer<ViewTotalItemProvider>(
builder: (context, value, child){
return Container(
height: 35,
width: 35,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50),
border: Border.all(color: Color(0xFF96CA2D),width: 4)
),
child: Center(child: Text(ourAllLists.totalquantity().toString(),style:TextStyle(fontSize: 20,color: Color(0xFF96CA2D)))),
);
}),
),
],
),
),
)
],
);
})
);
}
}
secondScreen ParticularPlant2
class ParticularPlant2 extends StatefulWidget {
final indexNumber;
ParticularPlant2({@required this.indexNumber});
@override
_ParticularPlant2State createState() => _ParticularPlant2State();
}
class _ParticularPlant2State extends State<ParticularPlant2> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TopAppBar(),
Container(
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadiusDirectional.only(
bottomStart: Radius.circular(50),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber].pN,
style: kPlantNameStyle,
),
Text(
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber].ca
.toUpperCase(),
style: TextStyle(
fontSize: 15,
),
),
Text(
"$" +
ourAllLists
.mainListAllPlantDetailsList1[widget.indexNumber]
.pr
.toString(),
style: kItemPrice,
),
SizedBox(height: 100),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(50)),
child: Icon(
FontAwesomeIcons.flag,
color: Color(0xFF9DCD3C),
),
),
SizedBox(
height: 50,
),
FlatButton(
onPressed: () {
final tile = cartPlantList3.firstWhere(
(item) =>
item.pN ==
ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pN,
orElse: () => null);
if (tile != null) {
} else {
cartPlantList3.add(
CartPlantLists(
quantity: 1,
plantName: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pN,
category: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.ca,
price: ourAllLists
.mainListAllPlantDetailsList1[
widget.indexNumber]
.pr,
),
);
}
print(cartPlantList3.length);
},
child: Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: Color(0xFF9DCD3C),
borderRadius: BorderRadius.circular(50)),
child: Icon(FontAwesomeIcons.shoppingBag,
color: Colors.white),
),
)
],
),
Container(
height: 250,
child: Image(image: AssetImage("assets/tulip.png")),
)
],
)
],
),
)
],
),
),
),
);
}
}
看来您使用 Provider 的方式不对。在您的场景中执行此操作的最佳方法是使用 MultiProvider 将 MaterialApp 包装在 main.dart 文件中的 MyApp() 中。尝试这样的事情:https://pub.dev/packages/provider#multiprovider 你可以在其中放置一个 ChangeNotifierProvider。
return MultiProvider(
providers: [
ChangeNotifierProvider<ViewTotalItemProvider>(
create: (context) => ViewTotalItemProvider()),
],
child: MaterialApp(...)
);
此外,您必须在模型中放置 getter 和 setter。这是一个例子:
class ImageModel extends ChangeNotifier {
String _base64Image;
get base64Image => _base64Image;
set base64Image(String base64Image) {
_base64Image = base64Image;
notifyListeners();
}
}
我还建议使用 Selector 而不是 Consumer(理想情况下,您应该使用 Selector 而不是 Consumer,以便小部件仅在其监听的值发生变化时才重建)这是一个基于上述模型的示例:
@override
Widget build(BuildContext context) {
//other widgets
Selector<ImageModel, String>(
selector: (_, model) => model.base64Image,
builder: (_, image, __) {
return Text(image);
},
);
}
)
}
以下是使用 RaisedButton 获取和设置它的方法:
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
final itemModel;
List<CartPlantLists> myList=[];
@override
Widget build(BuildContext context) {
itemModel = Provider.of<ViewTotalItemProvider>(context,listen:false);
print(itemModel.yourVariable); //getting the value
return Container(
child: RaisedButton(
child:Text("Set Item");
onPressed:(){
itemModel.yourVariable=myList; //setting the value
},
),
);
}
}
希望对您有所帮助!祝你好运!
第一步: 在 pubspec.yaml 文件
中添加对提供者模式的依赖dependencies:
flutter:
sdk: flutter
provider: ^4.1.2
第 2 步: 在单独的文件中创建提供程序:
class ViewTotalItemProvider with ChangeNotifier{
List<CartPlantLists> _cartPlantList1 = [];
get cartPlantList1 => _cartPlantList1 ;
set cartPlantList1 (List<CartPlantLists> selected){
_cartPlantList1 = selected;
notifyListeners();
}
}
第 3 步: 使用 MultiProvider 将 MaterialApp 小部件包装在 main.dart.
中
void main() => runApp(
MultiProvider (providers: [
ChangeNotifierProvider<ViewTotalItemProvider>.value(value:
ViewTotalItemProvider()),
],
child: MyApp()
)
);
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
第 4 步: 在屏幕中使用提供程序 PlantFeatureScreen1 :
class PlantFeatureScreen1 extends StatefulWidget {
@override
_PlantFeatureScreen1State createState() => _PlantFeatureScreen1State();
}
class _PlantFeatureScreen1State extends State<PlantFeatureScreen1> {
var viewTotalItemProvider;
@override
Widget build(BuildContext context) {
viewTotalItemProvider = Provider.of<ViewTotalItemProvider>(context);
return Scaffold(
.......
);
}
}
第 5 步: 获取 cartPlantList1.
List<CartPlantLists> list = viewTotalItemProvider.cartPlantList1;
第 6 步:设置 cartPlantList1。
List<CartPlantLists> list = [];
...
viewTotalItemProvider.cartPlantList1 = list;
类似地,你可以用于其他两个 类。