Issue
I have a service class in Flutter that fetches objects from the server using Rest API calls. It caches those objects and returns cached objects if the UI tries to fetch the same object again. Like this:
Future<User?> getUser(int userid) async{
User? u = _userCache.get(userid);
if(u == null) {
ApiResponse<User> ar = await _restapi.getUser(userid);
if (ar.successful && ar.data != null) {
u = ar.data!;
_userCache.add(userid,u);
}
}
return u;
}
Now, the problem that I am having is as follows: The UI requires the same User object multiple times while building a screen and so, it invokes getUser(id) multiple times. Ideally, it should return the cached User for the second and subsequent requests but the first request to the server hasn't completed yet and the cache does not have the User object (even though it will have the object a few seconds later). This causes the app to invoke the Rest API calls multiple times.
I want to basically have just one active/pending call to the RestAPI. Something like this:
Future<User?> getUser(int userid) async{
>>>> CHECK whether a call to backend is pending. If so, then wait here.<<<<
User? u = _userCache.get(userid); <--This call should now succeed
...same as before
}
Is this how it should be done? What is the right way to achieve this?
====== UPDATE =================
Based on @dangngocduc suggestion my getUser method now looks like this:
Future<User?> getUser(int userid) async{
User? u = _userCache.get(userid);
if(u == null) {
await userLock.synchronized( () async {
u = _userCache.get(userid);
if(u == null) {
ApiResponse<User> ar = await _uome.getUser(userid);
if (ar.successful && ar.data != null) {
u = ar.data!;
_userCache.add(userid, u!);
}
}});
}
return u;
}
Solution
Your issue is on first time, when we don't have cache and have multiple request for a user.
I think you can try with this package:
https://pub.dev/packages/synchronized
Let add your logic on synchronized.
Answered By - dangngocduc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.