问题描述
在我们的系统中,我们在 Pusher
和 Admin Panel
应用程序上都使用了 mobile
,在 Flutter
中,我想用 Pusher
和Riverpod
并在屏幕中使用带有 Hook
小部件的提供程序,这意味着我想在 Pusher
或 main
中实现 MyApp
并广播来自 {{1} 的接收数据在我们拥有它们的所有屏幕上,基本上我们必须在需要接收数据且难以维护应用程序的每个屏幕中使用 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
解决方法
要监听 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));