是否可以通过在 flutter 中使用 Provider 来跨页更新值?

Is possible update value cross pages by using Provider in flutter?

我正在与 Provider

合作
provider: ^4.1.2

我有 2 页:A、B。

页面A和B显示相同的简单设计,代码如下:

PageA.dart

class PageA extends StatelessWidget {

   var songTitle = '';

   @override
   Widget build(BuildContext c) {
     return Column(children: <Widget>[
         FloatingActionButton.extended(
            onPressed: () {
                 // LOGIC : TRANSFER TO PAGE B AFTER CLICKED BUTTON FROM PAGE A
                 Navigator.push(context, MaterialPageRoute(
                     builder: (context) => PageB()));
            },
            label: Text('Click'),
           ),
         ),
         Text('$songTitle');
         // STEP 2 : while page B already got `songTitle` 
         // to show on UI, I want `songTitle` also update on this page A 
         // in the same time
     ]);
      
  }
}

PageB.dart

class PageB extends StatelessWidget {

   var songTitle = '';

   @override
   Widget build(BuildContext c) {
     return Text('$songTitle');
   }

   @override
   void initState() {
     super.initState();

     // LOGIC : CALL API TO GET `songTitle` TO UPDATE ON UI
     api.request().then((title) {
        setState(() {
           this.songTitle = title;
           // STEP 1 : this causes update to page B 
           // show `songTitle` got from api success
        });
     });
   }

}

这些代码 运行 没有错误。

What I want is after Step 1 got songTitle data,

It will updated its data to page A (Step 2) and page B (Step 1) in the same time by using Provider (ex. Provider.of(context) ...)

认识的人,

请告诉我,

谢谢,

已更新 我已经在下面得到了正确的@Chichebe 答案。

你读过 Provider 的例子了吗?

  • 在 flutter 中不要让你的小部件处理逻辑操作,例如发出 API 请求,你可以在你的提供者中这样做,甚至更好地创建一个独立的 class 来处理 HTTP请求你,然后你将它注入你的提供者代码,

你可以这样做:

class Song{
  String title;

  Song(this.title);
}

class MyProvider extends ChangeNotifier{
   Song song;

   void getSongInformation(String song) async{
       try{
          final req = await doYourAPIRequest();
          song = Song(req['title']);

          notifyListeners(); // Notify the listeners about this change

       }catch(e){
          // handle the error
       }
   }
}

然后在您的小部件中

Consumer<Song>(
  builder: (context, song, child) {
    return Text(song.title);
  },
)

所以当你调用notifyListeners()时,任何正在监听歌曲变化的Widgets都会收到任何变化的通知,如果你只需要Provider通知单个歌曲变化,那么你也可以使用ValueNotifierProvider。此外,最好将您的 Consumer 尽可能深地放入 Widget 树中,以便仅重建依赖于该值的 Widget。

main.dart

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [ChangeNotifierProvider<Song>(create: (context) => Song())],
      child: MaterialApp(home: PageA()),
    );
  }
}

歌曲模型

class Song extends ChangeNotifier {
  String songTitle = 'Title';

  void updateSongTitle(String newTitle) {
    songTitle = newTitle;

    notifyListeners();
  }
}

pageA

class PageA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Consumer<Song>(builder: (context, song, child) {
          print('Consumer() : ${song.songTitle}');

          return Column(
            children: <Widget>[
              // SONG TITLE
              Text(song.songTitle),
              // Button
              MaterialButton(
                onPressed: () => Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => PageB()),
                ),
                child: Text('Button'),
              ),
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          );
        }),
      ),
    );
  }
}

页面B

class PageB extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return PageBState();
  }
}

class PageBState extends State<PageB> {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    Timer(Duration(seconds: 2), () {
      final song = Provider.of<Song>(context, listen: false);

      song.updateSongTitle('New Title');
    });
  }

  @override
  Widget build(BuildContext c) {
    return Container(
      child: Text('Page B'),
      color: Colors.white,
    );
  }
}

p/s :I understand that

  • use the Provider package in managing your state and passing data down your widget tree.
  • use ChangeNotifier alongside ChangeNotifierProvider to achieve this.