Anmol Singh
Anmol Singh

Reputation: 661

Riverpod in a class or outside of build Method?

I want to make a class and put similar methods together.

Riverpod works using ref which is only available through extending but how to use it in bare class which doesn't have any extends and build methods.

Model

class User {
final String uid;
final String username;
final String email;

User({required this.uid, required this.username, required this.email});}

StateNotifier

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

Place of use / a class

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
}

Upvotes: 2

Views: 6317

Answers (2)

Yuriy N.
Yuriy N.

Reputation: 6127

Here is the general-purpose solution.

  1. Create RefHolder which obtains Ref reference from DummyProvider. I called it Dummy koz it does not really provides anything.

    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;
     }
    }
    
  2. Read the provider from the MainApp build method to ensure the RefHolder singleton is created.

     Widget build(BuildContext context, WidgetRef ref) {
        ref.read(dummyProvider);
    
  3. Use from anywhere. For example, from the local notifications method:

    Future _showNotificationWithDefaultSound(notifPlugin) async {
    
      Ref ref = refHolder.ref;
    
      //use ref to get required info from providers
    

Github

Upvotes: 3

MSARKrish
MSARKrish

Reputation: 4134

@AnmolSingh While creating StateNotifierProvider you can directly pass User model class. I have modified your code. If you tap the fab button it will update userProvider provider state and it will refresh the UI. You can run this code in dartpad itself.

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: "[email protected]",
                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());

You can pass ref as parameter for any class

class FirestoreMethods
{
  FirestoreMethods(this.ref)
  final Ref ref;
}

Upvotes: 3

Related Questions