From 3bce4e51b96e33cfc7e122232770d4c5c8509727 Mon Sep 17 00:00:00 2001 From: Konstantin Date: Tue, 21 Sep 2021 19:33:27 +0600 Subject: [PATCH] trying to add sqlite caching functionality to cache firebase data --- lib/provider/api.dart | 32 +++++++ lib/provider/database.dart | 14 ++- lib/provider/sql_queries.dart | 12 ++- lib/screen/firestore_page.dart | 26 +++++- lib/screen/firestore_page_future.dart | 124 ++++++++++++++++++++++++++ lib/screen/home_page.dart | 4 +- lib/screen/login_page.dart | 2 +- 7 files changed, 206 insertions(+), 8 deletions(-) create mode 100644 lib/screen/firestore_page_future.dart diff --git a/lib/provider/api.dart b/lib/provider/api.dart index ec3c8f4..692d794 100644 --- a/lib/provider/api.dart +++ b/lib/provider/api.dart @@ -1,4 +1,6 @@ import 'dart:convert'; +import 'dart:ffi'; +import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fetchingapp/provider/database.dart'; import 'package:http/http.dart' as http; import 'package:flutter/foundation.dart' show kIsWeb; @@ -13,6 +15,36 @@ class ApiProvider { return _getFromDB(); } + Future getDataForFirestore() async { + return readCache().then((value) async { + if (value.isNotEmpty) { + print('READING FROM DB, NUMBER OF ENTRIES: ${value.length}'); + callFirestore(); + print('called firestore'); + + return value; + } else { + return callFirestore(); + + // return _getFromApi(); + } + }); + } + + Future callFirestore() async { + cleanDB(); + print('fetching from network'); + var data = await FirebaseFirestore.instance + .collection('flutter-caching') + .orderBy('name') + .get(); + var array = data.docs.map((e) { + return {'name': e['name']}; + }).toList(); + await addBatchOfFirestore(list: array); + return array; + } + Future _getFromDB() async { return readCache().then((value) { if (value.isNotEmpty) { diff --git a/lib/provider/database.dart b/lib/provider/database.dart index 274bbce..236da55 100644 --- a/lib/provider/database.dart +++ b/lib/provider/database.dart @@ -14,8 +14,20 @@ Future cacheDatabase() async { //read data Future> readCache() async { final db = await cacheDatabase(); + var cache = db.query('cache'); + print('db entries: $cache'); - return db.query('cache'); + return cache; +} + +Future addBatchOfFirestore({required List> list}) async { + final db = await cacheDatabase(); + final batch = db.batch(); + for (var item in list) { + batch.insert('cache', item, conflictAlgorithm: ConflictAlgorithm.replace); + } + await batch.commit(noResult: true); + print('batch insert complete'); } // add entry diff --git a/lib/provider/sql_queries.dart b/lib/provider/sql_queries.dart index 4ebecdf..429e32e 100644 --- a/lib/provider/sql_queries.dart +++ b/lib/provider/sql_queries.dart @@ -1,10 +1,16 @@ class Queries { + // String createCacheTable = ''' + // CREATE TABLE IF NOT EXISTS cache ( + // id INTEGER PRIMARY KEY, + // name TEXT, + // email TEXT, + // body TEXT + // ); + // '''; String createCacheTable = ''' CREATE TABLE IF NOT EXISTS cache ( id INTEGER PRIMARY KEY, - name TEXT, - email TEXT, - body TEXT + name TEXT ); '''; String dropCacheTable = 'DROP TABLE cache'; diff --git a/lib/screen/firestore_page.dart b/lib/screen/firestore_page.dart index a4d097f..0c618e3 100644 --- a/lib/screen/firestore_page.dart +++ b/lib/screen/firestore_page.dart @@ -1,4 +1,5 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fetchingapp/provider/database.dart'; import 'package:flutter/material.dart'; class FirestoreDataPage extends StatefulWidget { @@ -12,6 +13,9 @@ class _FirestoreDataPageState extends State { final textController = TextEditingController(); void addEntry() { + if (textController.text == '') { + return; + } FirebaseFirestore.instance .collection('flutter-caching') .add({'name': textController.text}); @@ -37,12 +41,32 @@ class _FirestoreDataPageState extends State { if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator()); } else { + print(snapshot.data!.docs.length); + var data = snapshot.data!.docs.map((e) { + return {'name': e['name']}; + }).toList(); + // cleanDB(); + addBatchOfFirestore(list: data); + var db = readCache().then((value) { + return value; + // if (value.isNotEmpty) { + // // print('reading from db'); + // // print('reading from db'); + // // return Text('database has data'); + // } + // print(value); + }); + + print('db: $db'); + // readCache(); + + // print(data); return ListView( children: snapshot.data!.docs.map((e) { return ListTile( title: Text(e['name']), trailing: IconButton( - icon: Icon(Icons.delete), + icon: const Icon(Icons.delete), onPressed: () { e.reference.delete(); }, diff --git a/lib/screen/firestore_page_future.dart b/lib/screen/firestore_page_future.dart new file mode 100644 index 0000000..94154b5 --- /dev/null +++ b/lib/screen/firestore_page_future.dart @@ -0,0 +1,124 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fetchingapp/provider/api.dart'; +import 'package:fetchingapp/provider/database.dart'; +import 'package:flutter/material.dart'; + +class FutureFireStore extends StatefulWidget { + const FutureFireStore({Key? key}) : super(key: key); + + @override + _FutureFireStoreState createState() => _FutureFireStoreState(); +} + +class _FutureFireStoreState extends State { + final textController = TextEditingController(); + + void addEntry() { + // if (textController.text == '') { + // return; + // } + FirebaseFirestore.instance + .collection('flutter-caching') + .add({'name': textController.text}); + textController.clear(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Firestore Data'), + ), + body: Column( + children: [ + Expanded( + child: Center( + child: FutureBuilder( + future: ApiProvider().getDataForFirestore(), + builder: (context, snapshot) { + if (!snapshot.hasData) { + return const Center(child: CircularProgressIndicator()); + } else { + // return Text(snapshot.data.toString()); + return ListView.builder( + itemCount: (snapshot.data as dynamic).length, + itemBuilder: (context, index) { + final entry = (snapshot.data as dynamic)[index]; + return ListTile( + title: Text(entry['name'].toString()), + leading: Icon(Icons.plus_one), + ); + }); + } + }), + )), + TextField( + controller: textController, + onEditingComplete: () { + addEntry(); + }, + decoration: InputDecoration( + prefixIcon: const Icon(Icons.add_circle), + labelText: "Input new value and click Save:", + suffixIcon: IconButton( + icon: const Icon(Icons.save), + splashColor: Colors.blue, + tooltip: "Post message", + onPressed: () { + FirebaseFirestore.instance + .collection('flutter-caching') + .add({'name': textController.text}); + textController.clear(); + }, + ))), + ], + ), + ); + } +} + +// StreamBuilder( +// stream: FirebaseFirestore.instance +// .collection('flutter-caching') +// .orderBy('name') +// .snapshots(), +// builder: (context, AsyncSnapshot snapshot) { +// if (!snapshot.hasData) { +// return const Center(child: CircularProgressIndicator()); +// } else { +// print(snapshot.data!.docs.length); +// var data = snapshot.data!.docs.map((e) { +// return {'name': e['name']}; +// }).toList(); +// // cleanDB(); +// addBatchOfFirestore(list: data); +// var db = readCache().then((value) { +// return value; +// // if (value.isNotEmpty) { +// // // print('reading from db'); +// // // print('reading from db'); +// // // return Text('database has data'); +// // } +// // print(value); +// }); + +// print('db: $db'); +// // readCache(); + +// // print(data); +// return ListView( +// children: snapshot.data!.docs.map((e) { +// return ListTile( +// title: Text(e['name']), +// trailing: IconButton( +// icon: const Icon(Icons.delete), +// onPressed: () { +// e.reference.delete(); +// }, +// ), +// ); +// }).toList(), +// ); +// } +// }, +// ), \ No newline at end of file diff --git a/lib/screen/home_page.dart b/lib/screen/home_page.dart index a8558a4..e095009 100644 --- a/lib/screen/home_page.dart +++ b/lib/screen/home_page.dart @@ -1,10 +1,10 @@ import 'package:fetchingapp/provider/database.dart'; import 'package:fetchingapp/provider/google_authentication.dart'; import 'package:fetchingapp/screen/firestore_page.dart'; +import 'package:fetchingapp/screen/firestore_page_future.dart'; import 'package:fetchingapp/screen/login_page.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; -import 'package:fetchingapp/screen/data_page.dart'; class HomePage extends StatelessWidget { const HomePage(this.user, {Key? key}) : super(key: key); @@ -40,7 +40,7 @@ class HomePage extends StatelessWidget { Navigator.push( context, MaterialPageRoute( - builder: (context) => const FirestoreDataPage()), + builder: (context) => const FutureFireStore()), ); }, ), diff --git a/lib/screen/login_page.dart b/lib/screen/login_page.dart index b0dfa2f..c6b5902 100644 --- a/lib/screen/login_page.dart +++ b/lib/screen/login_page.dart @@ -41,7 +41,7 @@ class _LoginPageState extends State { @override Widget build(BuildContext context) { - FirebaseService().signOutFromGoogle(); + // FirebaseService().signOutFromGoogle(); return Scaffold( appBar: AppBar( title: const Text('Login Screen'),