6

Flutter 中的 Stream builder 正在被召回。我不确定为什么。我相信问题可能是我在流构建器中有一个集团提供者。我的流 dataBloc.dataStream 没有改变,导致流构建器再次构建。不确定,我做错了什么。流构建器是否一次又一次地构建我的小部件,而流没有任何变化。显然这不是真的!正确的?

Widget build(context) {
        final DataBloc dataBloc = DataBlocProvider.of(context);
        print("dropdown build called again");                         
        // this doesn't print recursively so this is perfect.
        // So my build is not getting called again. 

        return StreamBuilder(
            stream: dataBloc.dataStream,
            builder: (context, snapshot) {

              //ToDo remove prints
              print("dropdown ${snapshot.data}");                     
             // there is no change in snapshot.data, however print is getting called recursively. This is bad and wrong
             // so my stream builder is getting called again, and this is wrong


              String key = dataElement.conditionalField;
              String _valueArray = dataElement.conditionalValues.toString();
              String conditionalValue =
                  _valueArray.substring(1, _valueArray.length - 1);
              Map<String, String> dataMap = snapshot.hasData ? snapshot.data : {};
              bool isVisible = true;

              if (key != "" &&
                  dataMap.containsKey(key) &&
                  dataMap[key] == conditionalValue.toString()) {
                isVisible = true;
              } else if (key != "") {
                isVisible = false;
              }

              return Visibility(
                child: BlocDropDownProvider(
                  fieldName: dataElement.key,
                  dataBloc: dataBloc,
                  child: Card(
                    color: Colors.grey[100],
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[
                        label,
                        new Container(
                          height: 8.0,
                        ),
                        dropDown,
                      ],
                    ),
                  ),
                ),
                visible: isVisible? true:false,
              );

控制台上的输出是:

I/flutter (14422): dropdown {idnumber: 10}
I/flutter (14422): dropdown {idnumber: 10}
4

1 回答 1

0

从给定的细节中,我无法以 1:1 的准确度基础真正复制这个问题。我遇到的类似情况是在更改StreamBuilder时再次调用build inside。ConnectionState

这是使用 StreamBuilder 发送 HTTP 请求的最小复制。此处的 HTTP 请求示例基于此Flutter Networking 指南

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  final streamController = StreamController();

  @override
  void initState() {
    super.initState();
    fetchAlbum().then((response) => streamController.add(response));
  }

  @override
  void dispose() {
    super.dispose();
    streamController.close();
  }

  @override
  Widget build(BuildContext context) {
    debugPrint('build');
    return StreamBuilder(
      stream: streamController.stream,
      builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
        debugPrint('Stream $snapshot');
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: snapshot.hasData
                ? Text('Album ${snapshot.data.title}')
                : Text('Waiting...'),
          ),
        );
      },
    );
  }

  Future<Album> fetchAlbum() async {
    final response =
        await http.get('https://jsonplaceholder.typicode.com/albums/1');

    if (response.statusCode == 200) {
      // If the server did return a 200 OK response,
      // then parse the JSON.
      return Album.fromJson(jsonDecode(response.body));
    } else {
      // If the server did not return a 200 OK response,
      // then throw an exception.
      throw Exception('Failed to load album');
    }
  }
}

class Album {
  final int userId;
  final int id;
  final String title;

  Album({this.userId, this.id, this.title});

  factory Album.fromJson(Map<String, dynamic> json) {
    return Album(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
    );
  }
}

在此处输入图像描述

再说一次,我建议不要太在意构建成本,只要构建中的小部件是可管理的。本文档中讨论了有关 Flutter 最佳实践的更多详细信息。

于 2020-11-11T09:02:04.703 回答