簡體   English   中英

顫振使用 Riverpod 在屏幕之間共享接收到的推送數據

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

在我們的系統,我們使用Pusher在我們兩個的Admin Panelmobile應用,在flutter我想包裝與整個應用程序的屏幕PusherRiverpod和使用供應商提供Hook的屏幕小部件,這意味着我要實現PushermainMyApp和在我們擁有的所有屏幕上廣播從Pusher接收到的數據,基本上我們必須在每個需要接收數據的屏幕中使用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類:

class AlarmNotificationData {
  final String data;

  const AlarmNotificationData(this.data);
}

要收聽riverpod變化,您需要useProvider(provider);

useProvider方法將監聽 provider 中的狀態變化,它是您模型類的當前實例

這也為您提供了對存儲在模型類中的通知程序狀態的引用

用這個:

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));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM