[英]How to properly use flutter riverpod to share data between widgets in different files?
[英]flutter share received pusher data between screens using Riverpod
在我們的系統,我們使用Pusher
在我們兩個的Admin Panel
和mobile
應用,在flutter
我想包裝與整個應用程序的屏幕Pusher
和Riverpod
和使用供應商提供Hook
的屏幕小部件,這意味着我要實現Pusher
在main
或MyApp
和在我們擁有的所有屏幕上廣播從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.