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

折月煮酒 提交于 2020-07-23 06:43:20

问题


I'm working with Provider

provider: ^4.1.2

I had 2 pages : A, B.

Page A and B show same simple design, with below codes :

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

}

These codes run with no bugs.

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) ...)

People who knows,

Please tell me,

Thank you,

UPDATED I got correct @Chichebe answer in below already.


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

Song Model

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 :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.



回答2:


Have you read the Provider examples?

  • In flutter don't let your widgets handle logic operations, such as making API requests, you could do that in your provider, and even better create an independent class that will handle HTTP requests for you, then you inject it in your provider code,

You could do something like that:

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
       }
   }
}

Then in your Widgets

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

So any Widgets that is listening for Song changes will be notified about any changes when you call notifyListeners(), if you only need the Provider to notify about a single Song change, then you can also use ValueNotifierProvider. Also, it's good practice to put your Consumer deep as possible in the Widget tree in order to rebuild only the Widgets that depends on that value.



来源:https://stackoverflow.com/questions/62148419/is-possible-update-value-cross-pages-by-using-provider-in-flutter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!