I am building an app using flutter and I'm using the flutter_bloc package for managing state. I have a simple Avatar widget used for displaying for displaying profile photo of a user.
/// A widget for displaying a user profile avatar.
class UserAvatar extends StatelessWidget {
/// The unique identifier for a particular user.
final int userId;
/// The size of the avatar.
final double radius;
UserAvatar({required this.userId, this.radius = 30}) {}
@override
Widget build(BuildContext context) {
context.read<UserInfoBloc>().add(UserInfoEvent.getUserInfo(userId));
return BlocBuilder<UserInfoBloc, UserInfoState>(
builder: (context, state) {
return state.when(initial: () {
return Text('Initial');
}, loading: () {
return Text('Loading');
}, loaded: (user) {
print(user);
return Container(
child: Avatar(
shape: AvatarShape.circle(radius),
loader: Center(
child: ClipOval(
child: Skeleton(
height: radius * 2,
width: radius * 2,
),
),
),
useCache: true,
sources: [NetworkSource(user.avatarUrl ?? '')],
name: user.firstName!.trim(),
onTap: () {
//TODO implement Navigation to profile page
},
),
);
}, error: () {
return Text('error');
});
},
);
}
}
My problem is that the widget will be used multiple times (when displaying a feed and there are contents by the same user). I initially just have the id of the user, then I try to make a network call and try to get the user. I've implemented some form of caching in my repository:
@LazySingleton(as: UserInfoRepository)
class UserInfoRepositoryImpl extends UserInfoRepository {
final GetUserInfoRemoteDataSource remoteDataSource;
final GetUserInfoLocalDataSource localDataSource;
UserInfoRepositoryImpl(
{required this.remoteDataSource, required this.localDataSource});
@override
Future<Either<Failure, User>> getUserInfo(int id) async {
try {
final existsInCache = localDataSource.containsUserModel(id);
if (existsInCache) {
return right(localDataSource.getUserModel(id));
} else {
final result = await remoteDataSource.getUserInfo(id);
localDataSource.cacheUserModel(result);
return right(result);
}
} on ServerExceptions catch (e) {
return left(e.when(() => Failure(),
requestCancelled: () => Failure.requestCancelled(),
unauthorisedRequest: () => Failure.unauthorisedRequest(),
badRequest: (e) => Failure.badRequest(e),
notFound: () => Failure.notFound(),
internalServerError: () => Failure.internalServerError(),
receiveTimeout: () => Failure.receiveTimeout(),
sendTimeout: () => Failure.sendTimeout(),
noInternetConnection: () => Failure.noInternetConnection()));
} on CacheException {
return left(Failure.cacheFailure());
}
}
}
Of course, I used the injectable package for dealing with my dependencies, and I've used the @LazySingleton annotation on the repository. But unfortunately, if I try to display two avatars of the same user, two separate network calls will be made. Of course, I don't want that. How can I solve this problem?