简体   繁体   English

颤振使用 Riverpod 在屏幕之间共享接收到的推送数据

[英]flutter share received pusher data between screens using Riverpod

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:在我们的系统,我们使用Pusher在我们两个的Admin Panelmobile应用,在flutter我想包装与整个应用程序的屏幕PusherRiverpod和使用供应商提供Hook的屏幕小部件,这意味着我要实现PushermainMyApp和在我们拥有的所有屏幕上广播从Pusher接收到的数据,基本上我们必须在每个需要接收数据的屏幕中使用Pusher ,并且应用程序难以维护,例如:

在此处输入图片说明

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:在这里你可以看到Pusher事件和监听器工作正常,没有任何问题:

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 SpashScreen类作为初始化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 Profile屏幕应该从Pusher接收数据,我将其实现到SplashScreen

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

alarmNotificationStateProvider : alarmNotificationStateProvider

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

AlarmNotification class: AlarmNotification类:

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

  static const _initialValue = AlarmNotificationData('');

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

AlarmNotificationData class: AlarmNotificationData类:

class AlarmNotificationData {
  final String data;

  const AlarmNotificationData(this.data);
}

To listen changes in riverpod you require useProvider(provider);要收听riverpod变化,您需要useProvider(provider);

The useProvider method will listen for state changes in provider, which is the current instance of your model class useProvider方法将监听 provider 中的状态变化,它是您模型类的当前实例

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);而不是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 read方法让你引用你的状态管理类(CounterNotifier),而不用监听状态的变化

I haven't seen your code of AlarmNotification , so I use a simple version below.我没有看到你的AlarmNotification代码,所以我在下面使用了一个简单的版本。

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.我想你对riverpod有点误解。 The MyApp seems only provide the event data but not consume it. MyApp似乎只提供事件数据而不使用它。 So the part you can just use StatelessWidget.(It is also suggested to use "context.read(someProvider)" if you only read not watch)所以部分你可以只使用StatelessWidget。(如果你只看不看,也建议使用“context.read(someProvider)”)

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).而其他需要数据的小部件只听alarmNotificationProvider (您可能需要导入文件才能看到它)。 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);
  }
}

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

make sure both screeens are under the changenotifier in widget tree,确保两个屏幕都在小部件树中的 changenotifier 下,

other option is pass your provider to login screen as argument and use changenotifier.value() in login screen,另一个选项是将您的提供者作为参数传递给登录屏幕,并在登录屏幕中使用 changenotifier.value(),

We are also using pusher.我们也在使用推送器。 We are using flutter_pusher package and notifications work as expected.我们正在使用 flutter_pusher 包,通知按预期工作。 you can initialize it by eg你可以通过例如初始化它

Pusher.init('API_KEY', PusherOptions(encrypted:true));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM