代码之家  ›  专栏  ›  技术社区  ›  rajap

使用setState()时Flutter会使屏幕闪烁浅蓝色

  •  0
  • rajap  · 技术社区  · 4 年前

    好吧,我找了很久,但一无所获。这个问题似乎是构建缓存的问题,但我找不到关于清除构建缓存的资源,也找不到任何关于如何解决这个特定问题的资源。

    我的代码如下:

    part of finance_app;
    
    class InvestmentDetail extends StatefulWidget {
      final String userEmail;
      final String userName;
      final String profilePic;
      final String providerID;
      final String uid;
      InvestmentDetail(
          {@required this.userEmail,
          @required this.userName,
          @required this.profilePic,
          @required this.providerID,
          @required this.uid});
      @override
      _InvestmentDetailState createState() => _InvestmentDetailState();
    }
    
    final FirebaseAuth _auth = FirebaseAuth.instance;
    
    class _InvestmentDetailState extends State<InvestmentDetail>
        with SingleTickerProviderStateMixin {
      bool firstRun = true;
      bool showMoney = true;
      bool readyToShowChart = false;
      var refreshkey = GlobalKey<RefreshIndicatorState>();
      LineChart chart;
      bool isTapped = false;
      Future<String> displayName() async {
        FirebaseUser _user = await FirebaseAuth.instance.currentUser();
        return _user.displayName;
      }
    
    // various other functions go here
    
      void createLine2() {
        print("working");
        Firestore.instance
            .collection("user/" + widget.userEmail + "/investmentHistory")
            .snapshots()
            .listen(
              (data) => {
                print(data),
                line1 = {},
                data.documents.forEach(
                  (doc) => {
                    print(doc["percentage"]),
                    line1[DateTime.fromMillisecondsSinceEpoch(
                        int.parse(doc.documentID).round())] = doc["percentage"],
                  },
                ),
                chart = !f.format(percentageChangeTotal).contains("-")
                    ? LineChart.fromDateTimeMaps(
                        [line1], [Colors.red], ['%'],
                      )
                    : LineChart.fromDateTimeMaps(
                        [line1], [Colors.green], ['%'],
                      ),
              },
            );
      }
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      void initState() {
        createLine2();
        super.initState();
      }
    
    
      
      @override
      Widget build(BuildContext context) {
        createLine2();
        return WillPopScope(
          onWillPop: () async => false,
          child: Scaffold(
            body: SafeArea(
              child: Column(
                children: <Widget>[
                  Expanded(
                    child: StreamBuilder<QuerySnapshot>(
                      stream: Firestore.instance
                          .collection(
                              'user/' + widget.userEmail + '/positionLabels')
                          .orderBy("Date", descending: true)
                          .orderBy("Time", descending: true)
                          .snapshots(),
                      builder: (BuildContext context,
                          AsyncSnapshot<QuerySnapshot> snapshot) {
                        if (snapshot.hasError) {
                          return new Text('Error: ${snapshot.error}');
                        }
                        if (!snapshot.hasData) {
                          return Padding(
                            padding: const EdgeInsets.all(50.0),
                            child: Center(
                              child: Text(
                                "Add your first transaction!\n\nTap your profile picture in the top right to add your first order",
                                style: TextStyle(color: Colors.white),
                                textAlign: TextAlign.center,
                              ),
                            ),
                          );
                        } else {
                          switch (snapshot.connectionState) {
                            case ConnectionState.none:
                              print("ConnectionState: NONE");
                              return Text(
                                'Select',
                                style: TextStyle(color: Colors.white),
                              );
                            case ConnectionState.waiting:
                              print("ConnectionState: WAITING");
                              return LinearProgressIndicator();
                            case ConnectionState.done:
                              print("ConnectionState: DONE");
                              return Text(
                                '\$${snapshot.data} (closed)',
                                style: TextStyle(color: Colors.white),
                              );
                            default:
                              return Column(
                                children: <Widget>[
                                  SearchBar(
                                      widget: widget,
                                      nodeOne: nodeOne,
                                      controller: controller),
                                  GestureDetector(
                                    onTap: () {
                                      setState(() {
                                        readyToShowChart = true;
                                      });
                                    },
                                    child: Column(
                                      children: <Widget>[
                                        Container(
                                          padding: EdgeInsets.only(
                                              top: 20,
                                              right: 10,
                                              left: 10,
                                              bottom: 5),
                                          height: 200,
                                          width: MediaQuery.of(context).size.width,
                                          child: AnimatedOpacity(
                                            duration: Duration(seconds: 2),
                                            opacity: readyToShowChart ? 1 : 0,
                                            child: AnimatedLineChart(
                                              chart,
                                              key: UniqueKey(),
                                            ),
                                          ),
                                        ),
                                        TotalPositionsWidget(
                                            f.format(
                                                getTotalMoneySpent(snapshot.data)),
                                            getTotalAccountValue(snapshot.data)),
                                        PositionsChangeWidget(
                                            workWithNumbers(snapshot.data),
                                            f.format(percentageChangeTotal)),
                                      ],
                                    ),
                                  ),
                                  Expanded(
                                    child: RefreshIndicator(
                                      color: Colors.white,
                                      onRefresh: () => refreshMain(snapshot.data),
                                      key: refreshkey,
                                      child: ListView(
                                        children: snapshot.data.documents.map(
                                          (DocumentSnapshot document) {
                                            return new AnimatedOpacity(
                                              opacity: 1.0,
                                              duration:
                                                  Duration(milliseconds: 1000),
                                              child: StockListTile(
                                                  document, widget.userEmail),
                                            );
                                          },
                                        ).toList(),
                                      ),
                                    ),
                                  ),
                                ],
                              );
                          }
                        }
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    

    简单来说:我有一个StreamBuilder,它有一个列作为子列。该列包含:

    • 搜索栏
    • “图形小部件”
    • 封装在手势检测器中的文本小部件
    • streamview中可刷新的数据库条目列表

    当我点击文本小部件并触发“设置状态”时,屏幕在执行命令之前会闪烁淡蓝色:

    tapping the Text widget three times

    Flutter似乎正在重建整个布局。

    一个较小的问题(尽管远没有闪烁的蓝屏那么重要)是,AnimatedOpacity和AnimatedCrossFade从未在这个小部件中实际动画化,但在其他小部件中却可以(例如SearchBar)

    我见过 this 例如,这与我所经历的相似,但我在这里不处理图像,所以我不知道该去哪里。

    我也尝试过Dart DevTools,我所能得到的只是(使用时间线中的自下而上视图)它陷入了“performLayout-->layout-->performLayout--gt;layout”循环中

    有人能给我指一下正确的方向吗?

    0 回复  |  直到 4 年前
        1
  •  3
  •   rajap    4 年前

    对于那些将来遇到这个问题的人,答案如下:

    Flutter在“setState”上重建了整个有状态的小部件,因此蓝闪是由重建整个小部件(基本上是整个应用程序)引起的。要删除flash,请将尽可能多的小部件转换为无状态小部件,这样在重建时,Flutter就不必再次重建每个小部件。