由于当前屏幕上的更新,防止 Flutter Provider 在前一屏幕中重建小部件

Posted

技术标签:

【中文标题】由于当前屏幕上的更新,防止 Flutter Provider 在前一屏幕中重建小部件【英文标题】:Prevent Flutter Provider from rebuilding widgets in previous screen due updates on current screen 【发布时间】:2020-01-04 12:30:09 【问题描述】:

我仍然在寻找更好的陈述来充分表达我的问题,所以在这里详细说明

使用Provider 允许根据会影响它们的更改重建小部件。太好了!。


假设在主屏幕上(比如HomePage)我通过一个开关在明暗之间切换主题。小部件在主屏幕上重建。 现在我导航到其他屏幕(比如NextScreen)。

这里有一个按钮可以让我再次切换主题。我切换主题,然后重建当前屏幕上的小部件(NextScreen)。但是 android Studio 上的 Flutter Performance 选项卡显示上一屏(HomePage)上的小部件也被重绘了。


所以,我的问题是

    为什么会这样? 有没有办法防止重建不在当前屏幕上的小部件,而仅在我们返回特定屏幕时重建它们?

我的代码是90行的简单例子

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

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider<ThemeState>(
      child: MaterialApp(
        home: HomePage(),
        routes: 
          "next": (context) => NextScreen(),
        ,
      ),
      builder: (BuildContext context) => ThemeState(),
    );
  


class HomePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Consumer<ThemeState>(builder: (BuildContext context, ThemeState value, Widget child) 
      return Theme(
        data: value.getTheme(),
        child: Scaffold(
          appBar: AppBar(),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              SwitchListTile(
                title: Text("Enable dark mode"),
                value: value.isDarkModeOn,
                onChanged: (_) => value.toggleTheme(),
              ),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: () => Navigator.pushNamed(context, "next"),
            child: Icon(Icons.navigate_next),
          ),
        ),
      );
    );
  


class NextScreen extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Consumer<ThemeState>(
      builder: (context, value, child) 
        return Theme(
          child: Scaffold(
            appBar: AppBar(
              title: Text("Next Screen"),
            ),
            body: Center(
              child: RaisedButton(
                onPressed: () => value.toggleTheme(),
                child: Text("Toggle theme"),
              ),
            ),
          ),
          data: value.getTheme(),
        );
      ,
    );
  


class ThemeState with ChangeNotifier 
  bool isDark = true;
  static ThemeData darkTheme = ThemeData.dark();
  static ThemeData lightTheme = ThemeData.light();

  ThemeData _currentTheme = darkTheme;

  ThemeData getTheme() => _currentTheme;

  get isDarkModeOn => isDark;

  toggleTheme() 
    _currentTheme = isDark ? lightTheme : darkTheme;

    isDark = !isDark;
    notifyListeners();
  


【问题讨论】:

【参考方案1】:

由于您的消费者提供者小部件是其他小部件的父小部件,因此当提供者在切换时更新时,消费者子小部件也会更新。

【讨论】:

以上是关于由于当前屏幕上的更新,防止 Flutter Provider 在前一屏幕中重建小部件的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 使用 MediaQuery 时防止重建

PhoneGap暂停事件,模糊当前屏幕以防止敏感数据显示在快照中

Flutter BloC 布尔更新状态

防止任何表上的意外更新/删除

Flutter 应用程序在 android studio 模拟器上完美运行,但不会超过物理设备上的加载屏幕

在 Flutter 中推送新页面时,Navigator 堆栈上的页面会重建