I am trying to make MVVM architecture with riverpod annotation. And Here are some example code snippets.
import ...
part 'invite_customer_usecase.g.dart';
@riverpod
class InviteCustomerUseCase extends _$InviteCustomerUseCase {
final ShopRepository _shopRepository;
final UntactRepository _untactRepository;
final ManagerRepository _managerRepository;
final UserRepository _userRepository;
InviteCustomerUseCase(
{required ShopRepository shopRepository,
required UntactRepository untactRepository,
required ManagerRepository managerRepository,
required UserRepository userRepository})
: _shopRepository = shopRepository,
_untactRepository = untactRepository,
_managerRepository = managerRepository,
_userRepository = userRepository;
@override
InviteCustomerUseCase build() {
return InviteCustomerUseCase(
shopRepository: _shopRepository,
untactRepository: _untactRepository,
managerRepository: _managerRepository,
userRepository: _userRepository);
}
}
import ...
part 'lobby_viewmodel.g.dart';
@riverpod
class LobbyViewModel extends _$LobbyViewModel {
final UntactRepository _untactRepository;
final ShopRepository _shopRepository;
final ManagerRepository _managerRepository;
final InviteCustomerUseCase _inviteCustomerUseCase;
LobbyViewModel(
{required UntactRepository untactRepository,
required ShopRepository shopRepository,
required ManagerRepository managerRepository,
required InviteCustomerUseCase inviteCustomerUseCase}) :
_untactRepository = untactRepository,
_shopRepository = shopRepository,
_managerRepository = managerRepository,
_inviteCustomerUseCase = inviteCustomerUseCase;
@override
LobbyViewModel build() {
return LobbyViewModel(
untactRepository: _untactRepository,
shopRepository: _shopRepository,
managerRepository: _managerRepository,
inviteCustomerUseCase: _inviteCustomerUseCase);
}
}
And
part 'local_storage_provider.g.dart';
@riverpod
FlutterSecureStorage secureStorage(SecureStorageRef ref) => const FlutterSecureStorage();
@riverpod
ManagerLocalStorage managerLocalStorage(ManagerLocalStorageRef ref) => ManagerLocalStorageImpl(storage: ref.watch(secureStorageProvider));```
part 'repository_provider.g.dart';
@riverpod
ShopRepository shopRepository(ShopRepositoryRef ref) => ShopRepositoryImpl(dio: authDio(), managerLocalStorage: ref.watch(managerLocalStorageProvider));
@riverpod
UntactRepository untactRepository(UntactRepositoryRef ref) => UntactRepositoryImpl(authDio: authDio());
@riverpod
ManagerRepository managerRepository(ManagerRepositoryRef ref) => ManagerRepositoryImpl(localStorage: ref.watch(managerLocalStorageProvider), dataSource: ref.watch(managerDataSourceProvider));
@riverpod
UserRepository userRepository(UserRepositoryRef ref) => UserRepositoryImpl(dataSource: ref.watch(userDataSourceProvider));
At the moment I defined providers like this. But I read and watched videos and it seems like I don't need to define like this. But just @riverpod annotation on the top of class keyword seems like it does the same thing.
My problem is
@override
InviteCustomerUseCase build() {
return InviteCustomerUseCase(
shopRepository: _shopRepository,
untactRepository: _untactRepository,
managerRepository: _managerRepository,
userRepository: _userRepository);
}
This part. I think it is a problem?
Some people wrote like this
class LobbyViewModel extends _$LobbyViewModel {
final UntactRepository _untactRepository = ref.watch(untactRepositoryProvider);
final ShopRepository _shopRepository = ref.watch(shopRepositoryProvider);
final ManagerRepository _managerRepository = ref.watch(managerRepositoryProvider);
final InviteCustomerUseCase _inviteCustomerUseCase = ref.watch(inviteCustomerProvider);
// No constructor
}
And I think this is a problem because I can't inject when I test. And also, when people use this class other team member won't know if it needs those repositories or usecases.
So, I am trying to use constructor.
They can be singletons. Only ViewModel can be shared in different pages(or screens). which means, sometimes, it needs to be invalidate/refresh
or keepAlive
when you use pop or push in router.
And of course, generally, way. I'd like to use ref.watch()
, ref.read
, ... in Widgets. I am using HookConsumerWidget (from flutter_hooks package.)
So, How can I improve my code?
Your main problem is that the
build
method in your classes should return some state of your class. Recall that you have it returning an instance of the class. Take a look at this example - (Async)NotifierProvider.Then, in the
build
method of your classes, you can safely watch (useref.watch
andref.listen
) to yourshopRepository
,UntactRepository
and others and quietly get their instances.In short, try doing something like this:
Useful links: