Flutter Provider - How to add more info to user model after login

251 Views Asked by At

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('Exception\n($e)\n(${e.toString()})');
        }
    }
}
}
2

There are 2 best solutions below

1
On

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

0
On

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