How to put data to Hivedb after fetching it from the firebase? And access data from Hivedb for 1 hour?

2.3k Views Asked by At

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.

2

There are 2 best solutions below

0
On BEST ANSWER

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.

1
On

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.