【问题标题】:Is possible update value cross pages by using Provider in flutter?是否可以通过在颤振中使用 Provider 来跨页面更新值?
【发布时间】:2020-09-20 17:02:25
【问题描述】:

我正在与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
        });
     });
   }

}

这些代码运行时没有错误。

我想要的是Step 1得到songTitle数据之后,

它会将其数据更新到页面 A (Step 2) 和页面 B (Step 1) 同时使用Provider(例如Provider.of(context) ...)

知道的人

请告诉我,

谢谢,

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

【问题讨论】:

    标签: flutter dart flutter-provider


    【解决方案1】:

    ma​​in.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();
      }
    }
    

    页面A

    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:我明白了

    • 使用 Provider 包管理您的状态并将数据向下传递到您的小部件树。
    • 使用 ChangeNotifier 和 ChangeNotifierProvider 来实现这一点。

    【讨论】:

    • 我已经得到并应用了这种方法,但它不起作用。如前。在问题中,在我申请后,只有在PageB 中的Consumer 被调用时才会触发notifyListener()。就我而言,我想在pageA 中调用Consumer,并调用pageB。谢谢你的解释,我的参考:stackoverflow.com/questions/57910630/…
    • 您是否用消费者包装了 PageA 和 PageB?
    • 我在 A 和 B 页面内使用了单独的 Consumer。你如何为它们包装它?您可以编辑答案吗?页面 A 转到页面 B 通过 onPress 操作使用 Navigator.push
    • 我已经编辑过了。应用新代码,现在应该可以为您工作了。
    • 你好@Chichebe,我按照这种方式作为编辑问题中的完整示例代码,但它不起作用。你能快速看看这个吗? (p/s:我不使用 HTTP 请求)
    【解决方案2】:

    您是否阅读过 Provider 示例?

    • 在颤振中不要让你的小部件处理逻辑操作,例如发出 API 请求,你可以在你的提供者中这样做,甚至更好地创建一个独立的类来为你处理 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() 时,任何正在监听歌曲更改的 Widget 都会收到任何更改的通知,如果您只需要 Provider 通知单个歌曲更改,那么您也可以使用 ValueNotifierProvider。此外,最好将您的 Consumer 置于 Widget 树的最深处,以便仅重建依赖于该值的 Widget。

    【讨论】:

    • 对不起,这与我的问题无关。我不会提醒 HTTP 请求解析数据并在 UI 上显示。
    猜你喜欢
    • 2021-06-07
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 2011-07-31
    • 1970-01-01
    相关资源
    最近更新 更多