【问题标题】:Calling SetState() to Update UI in Flutter在 Flutter 中调用 SetState() 更新 UI
【发布时间】:2021-10-07 17:11:28
【问题描述】:

我正在开发一个应用程序,但我无法调用 setState 来更新我的用户界面。
我想在按钮更改时更新屏幕。所以我添加了 2 个布尔值 _local_today 以在点击按钮时更改它。
我正在调用 statusGridViewer 并在 StatusGridViewer 组件中传递布尔值,但现在我无法访问构建小部件中的布尔值,即使在构造函数中声明它们之后也是如此。我附上了一张图片以供参考。 任何帮助将不胜感激,谢谢。

1: https://i.stack.imgur.com/W4cGQ.png

状态屏幕

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

import 'package:bubble_tab_indicator/bubble_tab_indicator.dart';

import 'package:Health_app/data/covidData.dart';
import 'package:Health_app/data/data.dart';


import 'package:Health_app/screens/covidBarChart.dart';


import 'package:Health_app/config/palatte.dart';
import 'package:Health_app/config/styles.dart';

import 'package:Health_app/widgets/custom_app_bar.dart';
import 'package:Health_app/widgets/statusGridViewer.dart';[enter image description here][1]

class StatusScreen extends StatefulWidget {
  @override
  _StatusScreenState createState() => _StatusScreenState();
}

class _StatusScreenState extends State<StatusScreen> {
  var _isInit = true;
  var _isLoading = false;

  var _local = false;
  var _today = false;

   get local {
    return _local;
  }

     get today {
    return _today;
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  void didChangeDependencies() {
    print("Didchangedependanciescalled");
    if (_isInit) {
      setState(() {
        _isLoading = true;
      });
      Provider.of<CovidData>(context, listen: true)
          .fetchAndSetDataCovid()
          .then((_) => {
                setState(() {
                  _isLoading = false;
                }),
              });
    }
    _isInit = false;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    

    return Scaffold(
      appBar: CustomAppBar(),
      backgroundColor: Palette.primaryColor,
      body: _isLoading
          ? Center(
              child: CircularProgressIndicator(),
            )
          : CustomScrollView(
              physics: ClampingScrollPhysics(),
              slivers: [
                _buildHeader(),
                _buildRegionTabBar(),
                _buildStateTabBar(),
                SliverPadding(
                  padding: const EdgeInsets.symmetric(horizontal: 10.0),
                  sliver: SliverToBoxAdapter(
                    child: StatusGridViewer(local,today),
                  ),
                ),
                SliverPadding(
                  padding: const EdgeInsets.symmetric(horizontal: 10.0),
                  sliver: SliverToBoxAdapter(
                    child: CovidBarChart(
                      covidCases: covidDailyCases,
                    ),
                  ),
                ),
              ],
            ),
    );
  }

  SliverPadding _buildHeader() {
    return SliverPadding(
      padding: const EdgeInsets.all(20.0),
      sliver: SliverToBoxAdapter(
        child: Center(
          child: Text(
            'Statistics',
            style: const TextStyle(
              color: Colors.white,
              fontSize: 25.0,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }

  SliverToBoxAdapter _buildRegionTabBar() {
    return SliverToBoxAdapter(
      child: DefaultTabController(
        length: 2,
        child: Container(
          margin: EdgeInsets.symmetric(horizontal: 20.0),
          height: 50.0,
          decoration: BoxDecoration(
            color: Colors.white24,
            borderRadius: BorderRadius.circular(25.0),
          ),
          child: TabBar(
            indicator: BubbleTabIndicator(
              tabBarIndicatorSize: TabBarIndicatorSize.tab,
              indicatorHeight: 40.0,
              indicatorColor: Colors.white60,
            ),
            labelStyle: Styles.tabTextStyle,
            labelColor: Colors.black,
            unselectedLabelColor: Colors.white,
            tabs: [
              Text('Local'),
              Text('Global'),
            ],
            onTap: (index) {
              print('Statmeaer changed ' + index.toString());
             
                if (index.isOdd) {
                  _local = !_local;
                }
             
            },
          ),
        ),
      ),
    );
  }

  SliverPadding _buildStateTabBar() {
    return SliverPadding(
      padding: EdgeInsets.all(20.0),
      sliver: SliverToBoxAdapter(
        child: DefaultTabController(
          length: 2,
          child: TabBar(
            indicatorColor: Colors.transparent,
            labelStyle: Styles.tabTextStyle,
            labelColor: Colors.white,
            unselectedLabelColor: Colors.white54,
            tabs: [
              Text('Today'),
              Text('Total'),
            ],
            onTap: (index) {
              print('Date to show details selected ' + index.toString());
              if (index.isOdd) {
                _today = !_today;
              }
            },
          ),
        ),
      ),
    );
  }
}

StateGrid 组件

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    
    import '../data/covidData.dart';
    
    
    class StatusGridViewer extends StatefulWidget {
    
      final bool localData;
      final bool todayData;
    
      StatusGridViewer(this.localData, this.todayData);
    
      @override
      _StatusGridViewerState createState() => _StatusGridViewerState();
    }
    
    class _StatusGridViewerState extends State<StatusGridViewer> {
      @override
      Widget build(BuildContext context) {
    
        final covidData = Provider.of<CovidData>(context);
        final dataInstance = covidData.data;
    
        
        return Container(
          height: MediaQuery.of(context).size.height * 0.25,
          color: Colors.white24,
          child: Column(
            children: [
              Flexible(
                child: Row(
                  children: [
                    
                    _buildStateCard("Total Cases", "count", Colors.yellow),
                    _buildStateCard("Total Deaths", "countDeath", Colors.red),
                  ],
                ),
              ),
              Flexible(
                child: Row(
                  children: [
                    _buildStateCard("Total Recovered", "countRec", Colors.green),
                    _buildStateCard("Total Active", "countAct", Colors.grey),
                  ],
                ),
              ),
            ],
          ),
        );
      }
    
      Expanded _buildStateCard(String name, String patCount, MaterialColor color) {
        return Expanded(
          child: Container(
            margin: EdgeInsets.all(8.0),
            padding: EdgeInsets.all(10.0),
            decoration: BoxDecoration(
              color: color,
              borderRadius: BorderRadius.circular(10.0),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  name,
                  style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                      fontSize: 20.0),
                ),
                Text(
                  patCount,
                  style: TextStyle(
                      color: Colors.black,
                      fontWeight: FontWeight.bold,
                      fontSize: 20.0),
                ),
              ],
            ),
          ),
        );
      }
    }

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    你需要使用widget.boolenName

    widget.localData
    //Not localData, because it's a stateful widget.
    

    【讨论】:

      【解决方案2】:

      您的代码中基本上应该考虑两个概念。

      第一个,正如我之前的答案中提到的,每当您在stateful widget 中声明变量时,您的扩展有状态类的state class 只能通过调用widget.variable 访问构造函数中的变量。 在这种情况下,您应该使用 widget.localData/todayData 而不是 localData/todayData

      第二个是关于状态管理的。由于您的 StatusGridViewer 是您的主页的直接子页面,因此每次 bool 值之一更改时,您都应该在主页中使用 setState() 以重建您的子页面。否则,即使在内部变量确实发生了变化,它也不会反映在您的 UI 上。

      尽管如此,您应该选择 setState 本身以外的状态管理解决方案,因为大多数时候您想要更新特定的 UI 块。 以下是一些选项:

      【讨论】:

      • 谢谢 Spots Solutions,非常有帮助的答案。我想从 API 获取数据并在我的屏幕上更新它。我设法将数据存储在一个局部变量中,并用 changeNotifierProvider 包装应用程序并将它们显示在屏幕上,改变布尔值
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-17
      • 2021-12-18
      • 1970-01-01
      • 2019-12-21
      • 1970-01-01
      • 1970-01-01
      • 2020-12-07
      相关资源
      最近更新 更多