Repository: flutter
Issue: StreamBuilder rebuilds with old Stream data when changing Streams
Labels: framework,a: quality,has reproducible steps,P2,found in release: 3.7,found in release: 3.9,team-framework,triaged-framework

Currently, after the first data from a stream is processed by StreamBuilder, StreamBuilder will only ever use actual stream data in its builder function.

This is a problem when we pass a new and unique different stream to the same StreamBuilder widget after it has been used for a bit.

When you pass a new Stream to a StreamBuilder after a first Stream has already been processed and built by it, due to didUpdateWidget the StreamBuilder will be built again and the builder function will execute.

However, the data passed to the builder function is from the old stream and does not reflect the fact that the stream being managed by the StreamBuilder has changed.

Obviously it's not possible to take the most recent value automatically from the stream to pass to the builder, however in this situation I feel that it is more correct the use the initialData until StreamBuilder can get a first value from the Stream itself.

It would be up to the user then to change the initialData along with the stream being passed in to the StreamBuilder, but that makes sense since that is what you have to do anyways when building the StreamBuilder for the first time.

I've included sample code below explaining the problem.
There is text showing the current information for the current build, along with two buttons.
One to add new data to the current stream, and one to switch the stream to a different one (back and forth).

Notice how when you push the switch streams button, a build occurs, but the data shown is still the old data from the old (possibly closed) stream.

```dart
import 'package:flutter/material.dart';
import 'dart:async';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: Center(
            child: StreamSwitcher(),
          ),
        ),
      ),
    );
  }
}

class StreamSwitcher extends StatefulWidget {
  @override
  _StreamSwitcherState createState() => _StreamSwitcherState();
}

class _StreamSwitcherState extends State<StreamSwitcher> {
  StreamController<String> _controller1;
  StreamController<String> _controller2;
  StreamController<String> _currentController;

  int _controller1Value = 0;
  int _controller2Value = 0;
  int _buildCount = 0;

  @override
  void initState() {
    super.initState();
    _controller1 = StreamController.broadcast();
    _controller2 = StreamController.broadcast();
    _currentController = _controller1;
  }

  @override
  void dispose() {
    _controller1.close();
    _controller2.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        StreamBuilder<String>(
          initialData:
              _currentController == _controller1 ? 'Initial 1' : 'Initial 2',
          stream: _currentController.stream,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text('BuildCount:${++_buildCount}:${snapshot.data}');
            } else {
              return Text('BuildCount:${++_buildCount}:No data');
            }
          },
        ),
        MaterialButton(
            child: const Text('Push To Stream'),
            onPressed: () {
              _currentController.add(_currentController == _controller1
                  ? 'Stream1:${++_controller1Value}'
                  : 'Stream2:${++_controller2Value}');
            }),
        MaterialButton(
            child: const Text('Switch Streams'),
            onPressed: () {
              setState(() {
                _currentController = _currentController == _controller1
                    ? _controller2
                    : _controller1;
              });
            }),
      ],
    );
  }
}
```

flutter doctor
```
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.17.2, on Mac OS X 10.15.6 19G2021, locale en-CA)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.2.1)
[✓] Android Studio (version 4.0)
[✓] VS Code (version 1.48.1)
[✓] Connected device (1 available)
```