Riverpod в классе или вне метода сборки?
Я хочу создать класс и объединить похожие методы.
Riverpod работает с использованием ref, который доступен только через расширение, но как его использовать в голом классе, который не имеет методов расширения и сборки.
Модель
class User {
final String uid;
final String username;
final String email;
User({required this.uid, required this.username, required this.email});}
Уведомление о состоянии
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/user.dart';
class UserProvider extends StateNotifier<User> {
UserProvider()
: super(User(
email: '',
username: 'default',
uid: '',
));
addUser(User user) {
state = user;
}}
Место использования / класс
import 'package:cloud_firestore/cloud_firestore.dart';
import '../providers/user_provider.dart';
import '../models/user.dart' as model;
class FirestoreMethods {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
// HOW TO USE RIVERPOD HERE IN PLACE OF PROVIDER.
// EXAMPLE OF PROVIDER-
// final user = Provider.of<UserProvider>(context, listen: false);
// print(user.email);
// print(user.uid);
// print(user.username);
// Example of Riverpod
// final userProvider = StateNotifierProvider<UserProvider,
// model.User>((ref) => UserProvider());
// ABOVE RIVERPOD DOES NOT WORK HERE
}
2 ответа
@AnmolSingh При создании StateNotifierProvider вы можете напрямую передать класс модели пользователя. Я изменил ваш код. Если вы нажмете потрясающую кнопку, она обновит состояние провайдера userProvider и обновит пользовательский интерфейс. Вы можете запустить этот код в самом дартпаде.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final user = ref.watch(userProvider);
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Text("UserName: ${user.username}"),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(userProvider.notifier).addUser(User(
email: "krishnakumar@riverpod.com",
uid: "1",
username: "MSARKrish",
));
},
),
));
}
}
class User {
final String uid;
final String username;
final String email;
User({required this.uid, required this.username, required this.email});
}
class UserProvider extends StateNotifier<User> {
UserProvider()
: super(User(
email: '',
username: 'default',
uid: '',
));
addUser(User user) {
state = user;
}
}
final userProvider =
StateNotifierProvider<UserProvider, User>((ref) => UserProvider());
Вы можете передать ref как параметр для любого класса
class FirestoreMethods
{
FirestoreMethods(this.ref)
final Ref ref;
}
Вот универсальное решение.
Создайте RefHolder, который получит
Ref
ссылка изDummyProvider
. Я назвал его Dummy, потому что на самом деле он ничего не дает.class DummyNotifier extends Notifier<bool> { @override bool build() { refHolder = RefHolder._(ref); return true; } } final dummyProvider = NotifierProvider<DummyNotifier, bool>(() { return DummyNotifier(); }); late RefHolder refHolder; class RefHolder { final Ref _ref; RefHolder._(this._ref); get ref { return _ref; } }
Прочтите поставщика из метода сборки MainApp, чтобы убедиться, что синглтон RefHolder создан.
Widget build(BuildContext context, WidgetRef ref) { ref.read(dummyProvider);
Используйте из любого места. Например, из метода локальных уведомлений:
Future _showNotificationWithDefaultSound(notifPlugin) async { Ref ref = refHolder.ref; //use ref to get required info from providers