简体   繁体   中英

How to change the value in static list from another page in flutter?

SITUATION

static list in FirstScreen.dart

static List<Shoe> shoeBank = [
    Shoe(iN:0,b: "Red Shoe", i: "assets/nikeShoeProduct1.jpg", q: 0,c: Color(0xFFC60635)),
    Shoe(iN:1,b: "White Shoe", i: "assets/nikeShoeProduct2.jpg", q: 0, c: Colors.white)
  ];

Explanation

I am changing one of the item value int from ThirdScreen.dart in the list. It does change in the list but does not show the updated value in the SecondScreen.dart screen? However, when I go back all the way to FirstScreen.dart then it does show the updated value in the second screen.

Tried

I have tried using SetState in the ThirdScreen.dart while updating the value.

Question

*How to make the SecondScreen.dart show the updated value when came back from ThirdScreen.dart and what might went wrong?

For a clean solution you need to make Store class that holds the list along with the list manipulation methods, then use a provider package for example to listen to all the changes that happens to the list.

Here is a small example:

class Store extends ChangeNotifier {
  var myList = <String>[];

  void add() {
    myList.add('new item');
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var pageNumber = 1;
    return MaterialApp(
      home: Scaffold(
        body: ChangeNotifierProvider(
          create: (_) => Store(),
          child: pageNumber == 1 ? FirstPage() : SecondPage(),
        ),
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var store = Provider.of<Store>(context);
    return Center(
      child: RaisedButton(onPressed: () => store.add()),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    var store = Provider.of<Store>(context);

    return Column(
      children: [
        ...store.myList.map((item) => Text(item)).toList(),
      ],
    );
  }
}

With provider package (RECOMMENDED!)

As Nour already pointed out you should make a Model class which holds your List<Shoe> . A static variable to store some changing data is never the way you should go.

The steps I would recommend are the following:

  1. Create a model class like ShoeStore which extends ChangeNotifier

  2. In this class you store you List<Shoe> and you write your methods to change this list. Important is that at the end of the methods you call notifyListeners .

  3. As the parent of your MaterialApp you create a MultiProvider widget where you initialize the ShoeStore

  4. There, where you need to access the ShoeStore you provide the widget Cosumer<ShoeStore> . And instead of a child you insert your children there in a builder property which gets the ShoeStore instance as an argument.

  5. Read this great guide! about Statemanagement with Provider for Flutter.

This is how your code could look like:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) =>
              ShoeStore([Shoe(name: "Nike"), Shoe(name: "Adidas")]),
        ),
      ],
      child: MaterialApp(
        home: Column(
          children: [
            Expanded(child: FirstScreen()),
            Expanded(child: SecondScreen()),
            Expanded(child: ThirdScreen())
          ],
        ),
      ),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      height: 100,
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<ShoeStore>(
      builder: (context, shoeStore, child) => Container(
        alignment: Alignment.center,
        color: Colors.blue,
        height: 100,
        child: Text("Number of shoes: ${shoeStore.shoes.length}",
            style: Theme.of(context).textTheme.headline4),
      ),
    );
  }
}

class ThirdScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<ShoeStore>(
      builder: (context, shoeStore, child) => Container(
        constraints: BoxConstraints.expand(),
        color: Colors.green,
        height: 100,
        child: FlatButton(
          child: Text(
            "Add Shoe",
            style: TextStyle(color: Colors.black),
          ),
          onPressed: () => shoeStore.addShoe(Shoe(name: "Bugatti")),
        ),
      ),
    );
  }
}

class ShoeStore extends ChangeNotifier {
  List<Shoe> _shoes;

  ShoeStore(List<Shoe> initialValue) {
    _shoes = initialValue;
  }

  List<Shoe> get shoes => _shoes;

  void addShoe(Shoe shoe) {
    _shoes.add(shoe);
    notifyListeners();
  }
}

class Shoe {
  String name;
  Shoe({this.name});
}

As you can see. The FirstScreen is now empty and you do not have to store you List there anymore.

Without any package (NOT RECOMMENDED!!!!)

Without any package I would inject the State of my App into the Widgets which have to read or write the fields of the state.

This would look like:

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  List<Shoe> _shoes = [Shoe(name: "Nike"), Shoe(name: "Adidas")];

  void addShoe(Shoe shoe) => setState(() {
    _shoes.add(shoe);
  });

  List<Shoe> get shoes => _shoes;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Column(
        children: [
          Expanded(child: FirstScreen()),
          Expanded(child: SecondScreen(this)),
          Expanded(child: ThirdScreen(this))
        ],
      ),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,
      height: 100,
    );
  }
}

class SecondScreen extends StatelessWidget {
  final MyAppState appState;

  SecondScreen(this.appState);

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      color: Colors.blue,
      height: 100,
      child: Text("Number of shoes: ${appState.shoes.length}",
          style: Theme.of(context).textTheme.headline4),
    );
  }
}

class ThirdScreen extends StatelessWidget {
  final MyAppState appState;

  ThirdScreen(this.appState);

  @override
  Widget build(BuildContext context) {
    return Container(
      constraints: BoxConstraints.expand(),
      color: Colors.green,
      height: 100,
      child: FlatButton(
        child: Text(
          "Add Shoe",
          style: TextStyle(color: Colors.black),
        ),
        onPressed: () => appState.addShoe(Shoe(name: "Bugatti")),
      ),
    );
  }
}

class Shoe {
  String name;
  Shoe({this.name});
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM