skip to Main Content

I’d like to add more info the following UserModel and make it available throughout all screens of the app. I’ve been struggling with the basics of Provider. Should I use a separate class extending the ChangeNotifier and store those additional properties there?
The example below is trying to add idVendor (id_vendor).
I could use ProviderOf on every place where I need that information but it would be a new request every time I do it.
Any help would be really appreciated:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:firebase_core/firebase_core.dart';
import 'dart:convert';
import 'package:firebase_auth/firebase_auth.dart';
import 'dart:async';
import 'package:http/http.dart' as http;

void main() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    runApp(const App());
}

class App extends StatelessWidget {
    const App({Key? key}) : super(key: key);
    @override
    Widget build(BuildContext context) {
        return MultiProvider(
            providers: [
                Provider<AuthRepository>(create: (_) => AuthRepository()),
                StreamProvider<UserModel?>(create: (context) =>
                    context.read<AuthRepository>().monitorAuthStateChanges,
                    initialData: null,
                ),
            ],
            child: const MaterialApp(home: AuthCheck()),
        );
    }
}

class AuthCheck extends StatelessWidget {
    const AuthCheck({Key? key}) : super(key: key);
    @override
    Widget build(BuildContext context) {
        final userModel = Provider.of<UserModel?>(context);
        if (userModel != null) {
            return const MainPage();
        } else {
            return const LoginScreen();
        }
    }
}

class UserModel {
    final String uid;
    late final int? idVendor;
    UserModel({required this.uid, this.idVendor});
}

class AuthRepository {
    final FirebaseAuth _fireAuth = FirebaseAuth.instance;

    Stream<UserModel?> get monitorAuthStateChanges {
        return _fireAuth.authStateChanges().map(_userModel);
    }

    UserModel? _userModel(User? user) {
        if (user != null) {
            return UserModel(uid: user.uid);
        } else {
            return null;
        }
    }

    Future<void> addInfoToUser() async {
        final userModel = _userModel(_fireAuth.currentUser);
        if (userModel != null) {
            String endPoint = '${ApiEndPoints.userIdVendor}';
            String url = endPoint.replaceAll('id', userModel.uid);
        try {
            final response = await http.get(Uri.parse(url), headers: {
                'Content-Type': 'application/json; charset=utf-8',
            }).timeout(const Duration(seconds: 60));
            if (response.statusCode == 200) {
                final Map<String, dynamic> jsonResponseBody =
                    jsonDecode(response.body);
                final List<dynamic> data = jsonResponseBody['data'];
                userModel.idVendor = data[0]['id_vendor'];
            }
        } on Exception catch (e) {
            return Future.error('Exceptionn($e)n(${e.toString()})');
        }
    }
}
}

2

Answers


  1. Chosen as BEST ANSWER

    I've just found the answer. Hence the data my changenotifierprovider is using comes from an API http request I had to use a Future, then I had to "await" for it asynchronously. Finally, after reading the package documentation on pub.dev, and since the obtained values are used just as static parameters, I was able to use them with an oneliner in the initState.

    https://pub.dev/packages/provider


  2. You can have copyWith method inside UserModel to assign or change idVendor parameter.

    class UserModel {
      UserModel({required this.uid, this.idVendor});
    
      final String uid;
      final int? idVendor;
    
      UserModel copyWith({String? uid, int? idVendor}) => UserModel(
            uid: uid ?? this.uid,
            idVendor: idVendor ?? this.idVendor,
          );
    }
    

    Then inside addInfo use _userModel.copywith(idVendor: newId);

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search