6

In our system we used Pusher on both of our Admin Panel and mobile application, in flutter i want to wrap whole application screens with Pusher and Riverpod and using providers with Hook widget in screens, that means i want to implement Pusher in main or MyApp and broadcast received data from Pusher on all of screens which we have them, basically we had to use Pusher in each screen which we need to receive data and its difficult to maintain application, for example:

enter image description here

this sample code is not correct and i tried to implement that, but i can't

here as you can see Pusher events and listeners work fine without any problem:

D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): [BIND] new-login
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): Event stream cancelled.
D/PusherClientPlugin( 7447): Event stream listening...
D/PusherClientPlugin( 7447): [BIND] new-login
D/PusherClientPlugin( 7447): [ON_EVENT] Channel: backers-list, EventName: new-login,
D/PusherClientPlugin( 7447): Data: Sending Test Data , User Id: null
I/flutter ( 7447): received

SpashScreen class as initializing Pusher

class SplashScreen extends HookWidget{
  @override
  Widget build(BuildContext context) {
    _routeNavigation();
    final PusherClient pusher = PusherClient(
        "xxxx",
        PusherOptions(
        cluster: 'us2',
    ));
    final Channel channel;

    pusher.connect();

    channel = pusher.subscribe("backers-list");

    channel.bind("new-login", (event) {
      print('received');
      context
          .read(alarmNotificationStateProvider.notifier)
          .increment('${event?.data.toString()}');
    });

    return Scaffold(
      /* ... */

Profile screen should be receive data from Pusher which i implemented that into SplashScreen

class Profile extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final alarmNotification = useProvider(alarmNotificationStateProvider);
    print('PUSH RECEIVED');
    /* ... */
}

alarmNotificationStateProvider :

final alarmNotificationStateProvider = StateNotifierProvider<AlarmNotification, AlarmNotificationData>(
      (ref) => AlarmNotification(),
);

AlarmNotification class:

class AlarmNotification extends StateNotifier<AlarmNotificationData> {
  AlarmNotification() : super(_initialValue);

  static const _initialValue = AlarmNotificationData('');

  void increment(String data) {
    state = AlarmNotificationData(data);
  }
}

AlarmNotificationData class:

class AlarmNotificationData {
  final String data;

  const AlarmNotificationData(this.data);
}
Tolga Kartal
  • 617
  • 4
  • 12
DolDurma
  • 15,753
  • 51
  • 198
  • 377

5 Answers5

1

To listen changes in riverpod you require useProvider(provider);

The useProvider method will listen for state changes in provider, which is the current instance of your model class

This also gives you a reference to the notifier state, which you’re storing in model class

use this:

final alarmNotificationNotifier  = useProvider(alarmNotificationProvider);

instead of final alarmNotificationNotifier = context.read(alarmNotificationProvider);

the read method gets you a reference to your state management class (CounterNotifier) without listening for changes in the state

Nik
  • 1,991
  • 2
  • 13
  • 30
  • 1
    this implementation is for `Provider` not `Riverpod` – DolDurma Jul 20 '21 at 05:05
  • @DolDurma Have you used useProvider method in your classes to listen for state changes? – Nik Jul 20 '21 at 05:13
  • i tried to implement that, but i can't, could you give me a sample how can i do that? your answer couldn't help me on implementation – DolDurma Jul 20 '21 at 05:16
  • 1
    Instead of writing lengthy example code here, to better understand concept I found this blog. This might help to you https://medium.com/flutter-community/flutter-riverpod-tutorial-counter-app-ed3aa758f02f – Nik Jul 20 '21 at 05:31
  • i should upgrade my account on `medium`, as we can't pay money in this site which boycotted our country i couldn't read document – DolDurma Jul 20 '21 at 05:46
  • 1
    try to open in incognito otherwise I will share you code – Nik Jul 20 '21 at 05:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235084/discussion-between-doldurma-and-nik). – DolDurma Jul 20 '21 at 05:53
  • @DolDurma updated example code in conversation – Nik Jul 20 '21 at 07:00
1

I haven't seen your code of AlarmNotification, so I use a simple version below.

class AlarmNotification extends ChangeNotifier{    
  var _data;
  String get data => _data;

  void receivedData(String data){
    _data = data;
    notifyListeners();
  }
}

I think you misunderstand a little about riverpod. The MyApp seems only provide the event data but not consume it. So the part you can just use StatelessWidget.(It is also suggested to use "context.read(someProvider)" if you only read not watch)

final alarmNotificationProvider = ChangeNotifierProvider((ref)=>AlarmNotification());

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

  @override
  Widget build(BuildContext context) {

    ...

    channel.bind("new-login", (event) {
      context
          .read(alarmNotificationProvider)
          .receivedData('${event?.data.toString()}');
    });

    ...
  }
}

And the other widgets that need the data just listen to the alarmNotificationProvider (you may need to import the file to see it). It will rebuild the widget once it gets the notification.

class OtherWidget extends HookWidget {
  const OtherWidget({Key? key}):super(key: key);

  @override
  Widget build(BuildContext context) {
    final alarmNotification = useProvider(alarmNotificationProvider);
    
    return Text(alarmNotification.data);
  }
}
yellowgray
  • 4,006
  • 6
  • 28
0

We are also using pusher. We are using flutter_pusher package and notifications work as expected. you can initialize it by e.g.

Pusher.init('API_KEY', PusherOptions(encrypted:true));
Tolga Kartal
  • 617
  • 4
  • 12
-1

Try it this way,

/// Code

 runApp(
  MultiProvider(
   providers: [
     ChangeNotifierProvider<SettingsProvider>(
       create: (context) => SettingsProvider(),
     ),   
   ],
   child: MyApp(),
  ),
 );

///

class SettingsProvider extends ChangeNotifier {
  Locale _currentLocale = Locale("en", "");
  String _languageCode = "en";

  Locale get getCurrentLocale => _currentLocale;

  String get getLanguageCode => _languageCode;

  void updateLocale(Locale locale) {
    Log.loga(title, "updateLocale: >>>> $locale");
    Log.loga(title, "updateLocale: toLanguageTag >>>> ${locale.toLanguageTag()}");

    this._currentLocale = locale;
    AppTranslations.load(locale);
    this._languageCode = locale.toLanguageTag();

  //notifyListeners();
  Future.delayed(Duration(seconds: 0)).then((value) {
    super.notifyListeners();
  });
 }
}

/// update data
Provider.of<SettingsProvider>(context, listen: false).updateLocale(locale);

/// get data
Provider.of<SettingsProvider>(context).getCurrentLocale
DholaHardik
  • 462
  • 1
  • 4
  • 7
-1

make sure both screeens are under the changenotifier in widget tree,

other option is pass your provider to login screen as argument and use changenotifier.value() in login screen,

Dipak Prajapati
  • 360
  • 1
  • 6