River_pod: ProviderListener missing events

Created on 13 Aug 2020  Â·  12Comments  Â·  Source: rrousselGit/river_pod

my code:

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

import 'events/event_base.dart';
import 'events/loading_event.dart';
import 'events/show_snackbar_event.dart';

final eventProvider = StateProvider<EventBase>((ref) => null);

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

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

class _MyHomePageState extends State<MyHomePage> {
  void onChange(StateController<EventBase> event) {
    print(event.state);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: ProviderListener(
          provider: eventProvider,
          onChange: onChange,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            context.read(eventProvider).state = LoadingEvent();
            context.read(eventProvider).state = ShowSnackbarEvent();
          },
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ));
  }
}

Expected:

flutter: Instance of 'LoadingEvent'
flutter: Instance of 'ShowSnackbarEvent'

actually

flutter: Instance of 'ShowSnackbarEvent'

LoadingEvent is skiped.

question

Most helpful comment

The thing is, Providers voluntarily do not call listeners immediately on change

This is for performance and maintainability reasons.

So you're better off with a custom WhateverListener for special objects

All 12 comments

In the documentation.
Even if a provider changes many times in a quick succession, onChange will be called only once, at the end of the frame.
but I think it should triggers onChange if state is changed instead of call only once at the end of the frame

What's the purpose?

In a task, maybe something I want to pass more than one event to UI handle.
an example: loading dialog is showing and my http request done, then I want to dismisDialog and show snackbar for result success or fail.

so still can pass successEvent to UI do both dismisDialog and showSnackbar but I think it will be more flexible if it is managed from providers.

Maybe you shouldn't use StateProvider and instead use StateNotifierProvider with a custom StateNotifier

What is that better than StateNotifier if I use StateNotifierProvider ?

Actually, I'm not sure what you're trying to accomplish by writing:

context.read(eventProvider).state = LoadingEvent();
context.read(eventProvider).state = ShowSnackbarEvent();

StateNotifier is not an event queue, nor are providers.

Why not write showDialog/Navigator.pop directly inside the onPressed?

Just for example. Actually I call it from providers.

So if I want to pass event like a queue to UI then what should i do ?

Vào 12:54, Th 5, 13 thg 8, 2020 Remi Rousselet notifications@github.com
đã viết:

Actually, I'm not sure what you're trying to accomplish by writing:

context.read(eventProvider).state = LoadingEvent();
context.read(eventProvider).state = ShowSnackbarEvent();

StateNotifier is not an event queue, nor are providers.

Why not write showDialog/Navigator.pop directly inside the onPressed?

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/rrousselGit/river_pod/issues/78#issuecomment-673277170,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AMRATJFY5NH4JELG2S54HNTSAN5YTANCNFSM4P5UKVMQ
.

Maybe do context.read(eventProvider).addListener(...)

I think addListener will be difficult to use in StatelessWidget or HookWidget because it should only be called once. So ProviderListener was born as a solution to the above problem and I think it should work like what addListener does as well.

The thing is, Providers voluntarily do not call listeners immediately on change

This is for performance and maintainability reasons.

So you're better off with a custom WhateverListener for special objects

Yes. maybe I need another way to solve it.
Thanks !

Was this page helpful?
0 / 5 - 0 ratings