Reputation: 432
I am trying to put data as a temporary storage in app for 1 hour.
I am fetching the data from Firestore:
static final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List<DocumentSnapshot>> fetchLeaderBoard() async {
final result =
await _firestore.collection('users').orderBy('points', descending: true).limit(10).get();
return result.docs;
}
And for storing it to HiveDb, I have done:
class _LeaderBoardState extends State<LeaderBoard> {
var _repository;
List<DocumentSnapshot> users;
Box box;
@override
void initState() {
_repository = Repository();
users = [];
super.initState();
openBox();
}
Future openBox() async {
var dir = await path_provider.getApplicationDocumentsDirectory();
Hive.init(dir.path);
box = await Hive.openBox('leaderBoard');
return;
}
Future<void> _fetchUsers() async {
users = await _repository.fetchLeaderBoard();
box.put('users',users);
print("HIVE DB : ");
print(box.get('users'));
}
}
Now, how to fetch it from Hivedb for 1 hour duration? And after 1 hour, data should be fetched again from Firestore.
Upvotes: 1
Views: 2548
Reputation: 14435
You'll need a few classes for this. Here's a simplified example:
class Repository {
final FirebaseApi api = FirebaseApi();
final HiveDatabase database = HiveDatabase();
Future<List<User>> getUsers() async {
final List<User> cachedUsers = await database.getUsers();
if(cachedUsers != null) {
return cachedUsers;
}
final List<User> apiUsers = await api.getUsers();
await database.storeUsers(apiUsers);
return apiUsers;
}
}
class FirebaseApi {
static final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List<User>> getUsers() async {
final result = await _firestore.collection('users').orderBy('points', descending: true).limit(10).get();
// convert List<DocumentSnapshot> to List<User>
return result.docs.map((snapshot) {
return User(
id: snapshot.id,
points: snapshot.data()['points'],
);
});
}
}
class HiveDatabase {
Future<List<User>> getUsers() async {
final DateTime lastUpdated = await _getLastUpdatedTimestamp();
if(lastUpdated == null) {
// no cached copy
return null;
}
final deadline = DateTime.now().subtract(Duration(hours: 1));
if(lastUpdated.isBefore(deadline)) {
// older than 1 hour
return null;
}
final box = Hive.openBox('leaderboard');
return box.get('users');
}
Future<void> storeUsers(List<User> users) async {
// update the last updated timestamp
await _setLastUpdatedTimestamp(DateTime.now());
// store the users
final box = Hive.openBox('leaderboard');
return box.put('users',users);
}
Future<DateTime> _getLastUpdatedTimestamp() async {
// TODO get the last updated time out of Hive (or somewhere else)
}
Future<void> _setLastUpdatedTimestamp(DateTime timestamp) async {
// TODO store the last updated timestamp in Hive (or somewhere else)
}
}
class User {
final String id;
final int points;
User({this.id, this.points});
}
Note: I don't have experience with Hive, so storing and reading might be changed a bit.
You'll need to have a repository that's responsible for checking the database first for valid data, and redirecting to the api if there's no valid cached data. When new data comes in from the api, the repository will tell the database to store it.
The database keeps track of the datetime when the data was stored, to check if it is still valid after an hour.
The important thing is that the database and the firebase api should not be aware of each other. They only know about the User
model and potentially their own models. If Hive needs other models to work with, map the User
to those models before storing and after reading.
Upvotes: 4
Reputation: 531
You will have to compare the DateTime to achieve this. Before reading data you read whether one hour has been past or not. To do this you will have to save the last read time in your hiveDB.
Upvotes: 0