MaterialApp 之上的 Flutter 重建提供者

Flutter rebuild provider above MaterialApp

在我的应用程序中,我在 MaterialApp 上方定义了一个提供程序 Song,以便通过我的应用程序访问它。


需要: 我这样做是因为我有一个 PageA,其中包含一个 songTitle 变量和一个转到 PageB 的按钮。 在 PageB 上,我有一个按钮可以调用我的提供商 Song 并更新 PageA。因此,当我在 PageB 上执行 Navigator.pop (context) 时,我回到 PageA 并查看更新后的 songTitle 变量。 为了能够从 PageB 更新 PageA,我必须将我的提供商 Song 置于 MaterialApp.

之上

==> 有效。


我的问题: 我希望能够在调用 PageA 时重置我的提供商。因此,如果我的 songTitle 变量已更新并且我退出 pageA,我希望我的 songTitle 变量在初始化提供者 Song 时 return 为其默认值.目前 songTitle 变量一直保持更新 ...


这里是路由器:

abstract class RouterClass{

  static Route<dynamic> generate(RouteSettings settings){
    final args = settings.arguments;

    switch(settings.name){

      case RouterName.kMenu:
        return CupertinoPageRoute(
            builder: (context) => Menu()
        );
      case RouterName.kPageA:
        return CupertinoPageRoute(
            builder: (context) => PageA()
        );
      case RouterName.kPageB:
        return CupertinoPageRoute(
            builder: (context) => PageB()
        );

      default:
        return CupertinoPageRoute(
            builder: (context) => Error404View(title: "Error")
        );
    }
  }
}

菜单:

class Menu extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('Menu'),
        ),
        body : Center(
          child: MaterialButton(
            onPressed: () {
              Navigator.pushNamed(
                    context,
                    RouterName.kPageA,
                  ),
            },
            child: Text('Button'),
          ),
        ),
      ),
    );
  }
}

A页:

class PageA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
        title: Text('pageA'),
      ),
        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.pushNamed(
                    context,
                    RouterName.kPageB,
                  ),
                  child: Text('Button'),
                ),
              ],
            );
          }),
        ),
      ),
    );
  }
}

页面B:

class PageB extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('pageB'),
        ),
        body : Center(
          child: MaterialButton(
            onPressed: () {
              Provider.of<Song>(context, listen: false).updateSongTitle('New Title');
            },
            child: Text('Button'),
          ),
        ),
      ),
    );
  }
}

提供商宋:

class Song extends ChangeNotifier {
  late String songTitle;

  Song(){
    _initialise();
  }

  Future _initialise() async
  {
    songTitle = "Title";
    notifyListeners();
  }

  void updateSongTitle(String newTitle) {
    songTitle = newTitle;

    notifyListeners();
  }
}

在页面 A 中使用 create:

child: ChangeNotifierProvider(
  create: (_) => Song(),
  child: Consumer<Song>(
    builder: (context, song, child) {
      print('Consumer() : ${song.songTitle}');
...

将您的 song 对象传递给 PageB:

Navigator.pushNamed(
  context,
  '/pageB',
  arguments: song,
);

在页面 B 中获取 song:

final song = ModalRoute.of(context)!.settings.arguments as Song;

完整代码:

// ignore_for_file: avoid_print

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

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      routes: {
        '/': (_) => const HomePage(),
        '/pageA': (_) => const PageA(),
        '/pageB': (_) => const PageB(),
      },
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: GestureDetector(
          onTap: () {
            Navigator.pushNamed(
              context,
              '/pageA',
            );
          },
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ),
    );
  }
}

class PageA extends StatefulWidget {
  const PageA({Key? key}) : super(key: key);

  @override
  State<PageA> createState() => _PageAState();
}

class _PageAState extends State<PageA> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ChangeNotifierProvider(
          create: (_) => Song(),
          child: Consumer<Song>(
            builder: (context, song, child) {
              print('Consumer() : ${song.songTitle}');
              return Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  // SONG TITLE
                  Text(song.songTitle),
                  // Button
                  MaterialButton(
                    onPressed: () {
                      Navigator.pushNamed(
                        context,
                        '/pageB',
                        arguments: song,
                      );
                    },
                    child: const Text('Button'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final song = ModalRoute.of(context)!.settings.arguments as Song;
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('pageB'),
        ),
        body: Center(
          child: MaterialButton(
            onPressed: () {
              song.updateSongTitle('New Title');
            },
            child: const Text('Button'),
          ),
        ),
      ),
    );
  }
}

class Song extends ChangeNotifier {
  late String songTitle;

  Song() {
    _initialise();
  }

  Future _initialise() async {
    songTitle = "Title";
    notifyListeners();
  }

  void updateSongTitle(String newTitle) {
    songTitle = newTitle;

    notifyListeners();
  }
}