0

Minimal reproducible code:

StreamController<int> _streamController = StreamController();

final provider1 = StreamProvider<int?>((ref) {
  return _streamController.stream.map((value) {
    print('listener1()');
    return value;
  });
});

final provider2 = StreamProvider<int?>((ref) {
  return ref.watch(provider1).maybeWhen(
    orElse: () => Stream.value(null),
    data: (value) {
      print('listener2()');
      return Stream.value(value);
    },
  );
});

class FooPage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.watch(provider2);
    return Scaffold(
      body: ElevatedButton(
        onPressed: () async {
          await _streamController.addStream(Stream.value(42));
          print('Done');
        },
        child: Text('Button'),
      ),
    );
  }
}

When you press the button, it prints:

I/flutter (15845): listener1()
I/flutter (15845): Done
I/flutter (15845): listener2()

But the correct order should be:

I/flutter (15845): listener1()
I/flutter (15845): listener2()
I/flutter (15845): Done

So, how can I fix this delay? Who is causing it?

iDecode
  • 22,623
  • 19
  • 99
  • 186
  • Stream takes some time to load data, so In order to execute data() log you need to use then() on signInAnonymously – Prashant Dec 30 '22 at 14:48
  • @Prashant `authStateChanges` is also a `Stream` but it didn't take any time to load data. What's your say on that? – iDecode Dec 30 '22 at 14:57

1 Answers1

0

I change code like below only delegating firebase job to add1()

import 'dart:async';

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

void main() {
  runApp(
    const ProviderScope(child: MaterialApp(home: MyApp())),
  );
}


final StreamController<int> streamController = StreamController.broadcast();

final provider1 = StreamProvider<int>((ref) {
  return streamController.stream.map((e) {
    print("provider1 : receive event");
    return e;
  });
});

final provider2 = StreamProvider<int>((ref) {
  return ref.watch(provider1).maybeWhen(
    orElse: () => Stream.value(-1),
    data: (user) {
      print('provider2 : value received from provider1');
      return Stream.value(user);
    },
  );
});


class MyApp extends ConsumerStatefulWidget {
  const MyApp({
    Key? key,
  }) : super(key: key);

  @override
  ConsumerState createState() => _MyAppState();
}

class _MyAppState extends ConsumerState<MyApp> {

  Future<void> add1() async {
    await Future.delayed(const Duration(seconds: 1));
    streamController.add(1);
    await Future.delayed(Duration.zero); // HERE!
  }

  @override
  Widget build(BuildContext context) {
    ref.watch(provider2);

    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await add1();
            print("button : clicked");
          },
          child: Text("click"),
        ),
      ),
    );
  }
}

As you can see in add1(), there is await Future.delayed(Duration.zero) at last. If click the button, there are two results.

provider1 : receive event
provider2 : value received from provider1
button : clicked

and

provider1 : receive event
button : clicked
provider2 : value received from provider1

But if this line is removed, you can see as you want

provider1 : receive event
provider2 : value received from provider1
button : clicked

So I think the reason is in the logic firebase work.

200_OK
  • 1
  • 1
  • Thanks but no, it's not related to Firebase but Riverpod. Check out my edited question. I removed `FirebaseAuth` from it. In your code, you're adding data synchronously which is not what I want. – iDecode Dec 30 '22 at 15:55
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 01 '23 at 06:00