通过在flutter中使用Provider可以更新跨页的值吗?

时间:2020-06-02 09:00:42

标签: flutter dart flutter-provider

我正在与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答案。

2 个答案:

答案 0 :(得分:1)

您阅读了提供程序示例吗?

  • 在混乱的情况下,不要让小部件处理逻辑操作(例如发出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()时,任何正在侦听Song更改的Widget都会收到有关任何更改的通知,如果您仅需要Provider来通知单个Song更改,那么也可以使用ValueNotifierProvider。另外,最好的做法是将“使用者”尽可能深地放在“小部件”树中,以便仅重建依赖于该值的小部件。

答案 1 :(得分:1)

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,
          );
        }),
      ),
    );
  }
}

pageB

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程序包管理状态并将数据传递到小部件树中。
  • 与ChangeNotifierProvider一起使用ChangeNotifier来实现这一目标。