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

问题描述

在我们的系统中,我们在 PusherAdmin Panel 应用程序上都使用了 mobile,在 Flutter 中,我想用 PusherRiverpod 并在屏幕中使用带有 Hook 小部件的提供程序,这意味着我想在 Pushermain 中实现 MyApp 并广播来自 {{1} 的接收数据在我们拥有它们的所有屏幕上,基本上我们必须在需要接收数据且难以维护应用程序的每个屏幕中使用 Pusher,例如:

enter image description here

这个示例代码不正确,我试图实现它,但我不能

在这里,您可以看到 Pusher 事件和侦听器正常工作,没有任何问题:

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

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 接收数据,我将其实现到 Pusher

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 AlarmNotification extends StateNotifier<AlarmNotificationData> { AlarmNotification() : super(_initialValue); static const _initialValue = AlarmNotificationData(''); void increment(String data) { state = AlarmNotificationData(data); } } 类:

AlarmNotificationData

解决方法

要监听 riverpod 中的更改,您需要 useProvider(provider);

useProvider 方法将侦听提供程序中的状态更改,即您的模型类的当前实例

这还为您提供了对存储在模型类中的通知程序状态的引用

使用这个:

final alarmNotificationNotifier  = useProvider(alarmNotificationProvider);

而不是final alarmNotificationNotifier = context.read(alarmNotificationProvider);

read 方法让您获得对状态管理类 (CounterNotifier) 的引用,而无需监听状态变化

,

我没有看到你的 AlarmNotification 代码,所以我在下面使用了一个简单的版本。

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

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

我想你对riverpod有点误解。 MyApp 似乎只提供事件数据,而不是使用它。所以这部分你可以只用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()}');
    });

    ...
  }
}

其他需要数据的小部件只听alarmNotificationProvider(您可能需要导入文件才能看到它)。它会在收到通知后重建小部件。

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

  @override
  Widget build(BuildContext context) {
    final alarmNotification = useProvider(alarmNotificationProvider);
    
    return Text(alarmNotification.data);
  }
}
,

试试这个方法,

/// 代码

 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
,

确保两个屏幕都在小部件树中的 changenotifier 下,

其他选项是将您的提供者作为参数传递给登录屏幕,并在登录屏幕中使用 changenotifier.value(),

,

我们也在使用推送器。我们正在使用 flutter_pusher 包,通知按预期工作。你可以通过 例如

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