Flutter local database nice animal :
This flutter tutorial post is generic (query, insert, insertAll, insertOrUpdateAll, update, delete, close, opern and getAll) sqflite local database and pagination.
dependencies:
sqflite:
http:
pagination :
Here quantity is null then value 10 consider.
final response = await http.get(‘https://shibe.online/api/${describeEnum(type)}?count=${quantity ?? 10}’);
sqflite flutter :
abstract class BaseRepository<T> { Future<R> query<R>(BaseSpecification<R> specification); Future<T> insert(T entity, {reload: true}); Future insertAll(List<T> entities); Future<T> insertOrUpdate(T entity); Future insertOrUpdateAll(List<T> entities); Future update(T entity); Future delete(T entity); Future close(); Future open(); Future<List<T>> getAll(); Future<String> getAppDBPath() async { var databasesPath = await getDatabasesPath(); // Make sure the directory exists try { await Directory(databasesPath).create(recursive: true); } catch (_) {} return join(databasesPath, Constants.databaseName); } } class NicePictureRepository extends BaseRepository<NicePicture> { static const String tableAnimalPicture = 'NicePicture'; static const String columnPictureURL = "picture_url"; static const String columnType = "animal_type"; Database db; static Map<String, dynamic> entityToMap(NicePicture picture) { return { columnPictureURL: picture.url, columnType: describeEnum(picture.type) }; } static NicePicture mapToEntity(Map<String, dynamic> map) { var type = map[columnType]; return NicePicture(map[columnPictureURL] as String, AnimalType.values.firstWhere((it) => describeEnum(it) == type)); } @override Future<List<NicePicture>> getAll() async { var list = await db.query(tableAnimalPicture); return list.map((map) => mapToEntity(map)).toList(); } @override Future<R> query<R>(BaseSpecification<R> specification) async { return specification.toResults(db); } @override Future<NicePicture> insert(NicePicture entity, {reload: true}) async { await db.insert(tableAnimalPicture, entityToMap(entity)); return entity; } @override Future<NicePicture> insertOrUpdate(NicePicture entity, {reload: true}) async { await db.insert(tableAnimalPicture, entityToMap(entity), conflictAlgorithm: ConflictAlgorithm.replace); return entity; } @override Future insertAll(List<NicePicture> entities) async { var transactions = entities.map((entity) => insert(entity)); await Future.wait(transactions); } @override Future insertOrUpdateAll(List<NicePicture> entities) async { var transactions = entities.map((entity) => insertOrUpdate(entity)); await Future.wait(transactions); } @override Future update(NicePicture entity) async { await db.update(tableAnimalPicture, entityToMap(entity)); } @override Future delete(NicePicture entity) async { await db.delete(tableAnimalPicture, where: '$columnPictureURL = ?', whereArgs: [entity.url]); } @override Future close() async { db.close(); } @override Future open() async { var path = await getAppDBPath(); db = await openDatabase(path, version: 1, onCreate: _onCreate); } Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE $tableAnimalPicture ( $columnPictureURL TEXT PRIMARY KEY NOT NULL, $columnType TEXT NOT NULL ) '''); } }
Screenshot :

Packages :
- base Package
- communicationlayer Package
- model Package
- ui Package
Inside base Package
base_repository.dart
import 'dart:io'; import 'package:nice_animals/ui/util/app_constants.dart'; import 'package:nice_animals/base/base_specification.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; abstract class BaseRepository<T> { Future<R> query<R>(BaseSpecification<R> specification); Future<T> insert(T entity, {reload: true}); Future insertAll(List<T> entities); Future<T> insertOrUpdate(T entity); Future insertOrUpdateAll(List<T> entities); Future update(T entity); Future delete(T entity); Future close(); Future open(); Future<List<T>> getAll(); Future<String> getAppDBPath() async { var databasesPath = await getDatabasesPath(); // Make sure the directory exists try { await Directory(databasesPath).create(recursive: true); } catch (_) {} return join(databasesPath, Constants.databaseName); } }
base_specification.dart
import 'package:sqflite/sqflite.dart'; abstract class BaseSpecification<T> { Future<T> toResults(Database db); }
Inside communicationlayer Package
all_by_type.dart
import 'package:flutter/foundation.dart'; import 'package:nice_animals/base/base_specification.dart'; import 'package:nice_animals/model/nice_picture.dart'; import 'package:sqflite/sqflite.dart'; import 'nice_picture_repository.dart'; class AllByType extends BaseSpecification<List<NicePicture>> { AnimalType type; AllByType(AnimalType type) { this.type = type; } @override Future<List<NicePicture>> toResults(Database db) async { var results = await db.query(NicePictureRepository.tableAnimalPicture, where: '${NicePictureRepository.columnType} = ?', whereArgs: [describeEnum(type)]); return results.map((it) => NicePictureRepository.mapToEntity(it)).toList(); } }
nice_picture_repository.dart
import 'package:flutter/foundation.dart'; import 'package:nice_animals/base/base_repository.dart'; import 'package:nice_animals/base/base_specification.dart'; import 'package:nice_animals/model/nice_picture.dart'; import 'package:sqflite/sqflite.dart'; class NicePictureRepository extends BaseRepository<NicePicture> { static const String tableAnimalPicture = 'NicePicture'; static const String columnPictureURL = "picture_url"; static const String columnType = "animal_type"; Database db; static Map<String, dynamic> entityToMap(NicePicture picture) { return { columnPictureURL: picture.url, columnType: describeEnum(picture.type) }; } static NicePicture mapToEntity(Map<String, dynamic> map) { var type = map[columnType]; return NicePicture(map[columnPictureURL] as String, AnimalType.values.firstWhere((it) => describeEnum(it) == type)); } @override Future<List<NicePicture>> getAll() async { var list = await db.query(tableAnimalPicture); return list.map((map) => mapToEntity(map)).toList(); } @override Future<R> query<R>(BaseSpecification<R> specification) async { return specification.toResults(db); } @override Future<NicePicture> insert(NicePicture entity, {reload: true}) async { await db.insert(tableAnimalPicture, entityToMap(entity)); return entity; } @override Future<NicePicture> insertOrUpdate(NicePicture entity, {reload: true}) async { await db.insert(tableAnimalPicture, entityToMap(entity), conflictAlgorithm: ConflictAlgorithm.replace); return entity; } @override Future insertAll(List<NicePicture> entities) async { var transactions = entities.map((entity) => insert(entity)); await Future.wait(transactions); } @override Future insertOrUpdateAll(List<NicePicture> entities) async { var transactions = entities.map((entity) => insertOrUpdate(entity)); await Future.wait(transactions); } @override Future update(NicePicture entity) async { await db.update(tableAnimalPicture, entityToMap(entity)); } @override Future delete(NicePicture entity) async { await db.delete(tableAnimalPicture, where: '$columnPictureURL = ?', whereArgs: [entity.url]); } @override Future close() async { db.close(); } @override Future open() async { var path = await getAppDBPath(); db = await openDatabase(path, version: 1, onCreate: _onCreate); } Future _onCreate(Database db, int version) async { await db.execute(''' CREATE TABLE $tableAnimalPicture ( $columnPictureURL TEXT PRIMARY KEY NOT NULL, $columnType TEXT NOT NULL ) '''); } }
shibe_service.dart
import 'dart:async'; import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:nice_animals/model/nice_picture.dart'; class ShibeService { static Future<List<NicePicture>> get(AnimalType type, {int quantity}) async { final response = await http.get( 'https://shibe.online/api/${describeEnum(type)}?count=${quantity ?? 10}'); // ignore: avoid_as final jsonResponse = json.decode(response.body) as List<dynamic>; return jsonResponse .cast<String>() .map((url) => NicePicture(url, type)) .toList(); } }
Inside model Package
nice_picture.dart
enum AnimalType { shibes, cats, birds } class NicePicture { String url; AnimalType type; NicePicture(String url, AnimalType type) { this.url = url; this.type = type; } }
Inside ui Package
There are three Packages inside ui package
- pages Package
- util Package
- widgets Package
Inside pages Package
animal_page.dart
import 'package:flutter/material.dart'; import 'package:nice_animals/communicationlayer/all_by_type.dart'; import 'package:nice_animals/communicationlayer/nice_picture_repository.dart'; import 'package:nice_animals/communicationlayer/shibe_service.dart'; import 'package:nice_animals/model/nice_picture.dart'; import 'package:nice_animals/ui/util/listener/bottom_reach.dart'; import 'package:nice_animals/ui/util/nice_navigator.dart'; import 'package:nice_animals/ui/widgets/animal_card.dart'; import 'package:nice_animals/ui/widgets/app_loader.dart'; class AnimalListScreen extends StatefulWidget { const AnimalListScreen(this.type) : super(); final AnimalType type; @override _AnimalListScreenState createState() => _AnimalListScreenState(type); } class _AnimalListScreenState extends State<AnimalListScreen> with AutomaticKeepAliveClientMixin<AnimalListScreen> { _AnimalListScreenState(this.type); final repository = NicePictureRepository(); ScrollController listController = ScrollController(); bool hasLoaded = false; bool isLoadingMore = false; List<NicePicture> animals = []; AnimalType type; @override bool get wantKeepAlive => true; void loadMoreShibes() async { setState(() { isLoadingMore = true; }); final loadedAnimals = await ShibeService.get(type); setState(() { animals = animals + loadedAnimals; isLoadingMore = false; }); } void loadShibes() async { await repository.open(); var loadedAnimals = await repository.query(AllByType(type)); if (loadedAnimals.isEmpty) { loadedAnimals = await ShibeService.get(type); } await repository.insertOrUpdateAll(loadedAnimals); await repository.close(); setState(() { animals = loadedAnimals; hasLoaded = true; }); } @override void initState() { super.initState(); if (!hasLoaded) { loadShibes(); OnBottomReach(listController, () { if (!isLoadingMore) { loadMoreShibes(); } }, sensitivity: 400.0); } } void _openPicture(int index) { NiceNavigator.goToGallery(context, initialPage: index, list: animals); } @override Widget build(BuildContext context) { if (!hasLoaded) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[AppLoader()], )); } else { return GridView.count( crossAxisCount: 2, controller: listController, children: List.generate(animals.length, (index) { return Container( padding: const EdgeInsets.all(3.5), child: AnimalCard( picture: animals[index], onTap: () { _openPicture(index); }), ); }), ); } } }
nice_fullscreen_gallery.dart
import 'package:flutter/material.dart'; import 'package:nice_animals/model/nice_picture.dart'; import 'package:nice_animals/ui/util/nice_navigator.dart'; class NiceFullScreenGallery extends StatefulWidget { const NiceFullScreenGallery({@required this.initialPage, @required this.list}) : super(); final int initialPage; final List<NicePicture> list; @override _NiceFullScreenGalleryState createState() => _NiceFullScreenGalleryState(initialPage, list); } class _NiceFullScreenGalleryState extends State<NiceFullScreenGallery> { _NiceFullScreenGalleryState(this.initialPage, this.list) : super() { controller = PageController(initialPage: initialPage); NiceNavigator.setStatusBarState(shown: false); } List<NicePicture> list; int initialPage; PageController controller; @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () { NiceNavigator.setStatusBarState(shown: true); Navigator.pop(context, true); }, child: Scaffold( backgroundColor: Colors.black, body: PageView.builder( controller: controller, physics: const AlwaysScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { return Image.network( list[index].url, fit: BoxFit.cover, ); }, ), ), ); } }
nice_home_screen.dart
import 'package:flutter/material.dart'; import 'package:nice_animals/model/nice_picture.dart'; import 'package:nice_animals/ui/pages/animal_page.dart'; class NiceHomeScreen extends StatefulWidget { @override _NiceHomeState createState() => _NiceHomeState(); } class _NiceHomeState extends State<NiceHomeScreen> with SingleTickerProviderStateMixin { TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(vsync: this, initialIndex: 1, length: 3); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Nice Animals'), elevation: 0.7, bottom: TabBar( controller: _tabController, indicatorColor: Colors.accents.first, tabs: const <Widget>[ Tab(text: 'Cats'), Tab(text: 'Shibes'), Tab(text: 'Birbs'), ], ), ), body: TabBarView( controller: _tabController, children: const <Widget>[ AnimalListScreen(AnimalType.cats), AnimalListScreen(AnimalType.shibes), AnimalListScreen(AnimalType.birds), ], ), ); } }
nice_splash_screen.dart
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:nice_animals/ui/util/nice_navigator.dart'; import 'package:nice_animals/ui/widgets/app_loader.dart'; class SplashScreenPage extends StatefulWidget { const SplashScreenPage({Key key, this.title}) : super(key: key); final String title; @override _SplashScreenPageState createState() => _SplashScreenPageState(); } class _SplashScreenPageState extends State<SplashScreenPage> { @override void initState() { super.initState(); Timer(Duration(seconds: 2), () => NiceNavigator.goToHome(context)); } @override Widget build(BuildContext context) { // This method is rerun every time setState is called, for instance as done // by the _incrementCounter method above. // // The Flutter framework has been optimized to make rerunning build methods // fast, so that you can just rebuild anything that needs updating rather // than having to individually change instances of widgets. return Scaffold( backgroundColor: Colors.amber, body: Stack( children: <Widget>[ Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Image.asset('assets/main_icon.png', width: 100.0), Text( 'Nice Animals', style: Theme.of(context).textTheme.display1, ), Container( margin: const EdgeInsets.only(top: 40.0), child: AppLoader(), ) ], ), ), ], )); } }
Inside util Package
- listener Package
- app_constants.dart
- nice_navigator.dart
app_constants.dart
class Constants { static const databaseName = 'nice.db'; }
nice_navigator.dart
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:nice_animals/model/nice_picture.dart'; import 'package:nice_animals/ui/pages/nice_fullscreen_gallery.dart'; class NiceNavigator { static void goToHome(BuildContext context) { Navigator.pushReplacementNamed(context, '/home'); } static void goToGallery(BuildContext context, {@required int initialPage, @required List<NicePicture> list}) { Navigator.push( context, MaterialPageRoute( builder: (context) => NiceFullScreenGallery( initialPage: initialPage, list: list, ), ), ); } static void setStatusBarState({@required bool shown}) { if (shown) { SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values); } else { SystemChrome.setEnabledSystemUIOverlays([]); } } }
Inside listener Package
bottom_reach.dart
import 'package:flutter/material.dart'; class OnBottomReach { OnBottomReach(ScrollController container, VoidCallback callback, {double sensitivity: 200.0}) { container.addListener(() { final maxScroll = container.position.maxScrollExtent; final currentScroll = container.position.pixels; if (maxScroll - currentScroll <= sensitivity) { callback(); } }); } }
Inside widgets Package
animal_card.dart
import 'package:flutter/material.dart'; import 'package:nice_animals/model/nice_picture.dart'; class AnimalCard extends StatelessWidget { const AnimalCard({@required this.picture, this.onTap}) : super(); final NicePicture picture; final VoidCallback onTap; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: ClipRRect( borderRadius: BorderRadius.circular(2.0), child: Image.network( picture.url, fit: BoxFit.cover, )), ); } }
app_loader.dart
import 'package:flutter/material.dart'; class AppLoader extends StatelessWidget { @override Widget build(BuildContext context) { return const CircularProgressIndicator( value: null, valueColor: AlwaysStoppedAnimation<Color>(Colors.black54) ); } }
Outside All Packages
main.dart
import 'package:flutter/material.dart'; import 'package:nice_animals/ui/pages/nice_home_screen.dart'; import 'package:nice_animals/ui/pages/nice_splash_screen.dart'; import 'package:sqflite/sqflite.dart'; void main() => runApp(MyApp()); var routes = <String, WidgetBuilder>{ "/home": (context) => NiceHomeScreen(), }; class MyApp extends StatelessWidget { MyApp() { assert(() { Sqflite.setDebugModeOn(true); return true; }()); } @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Tutorial', theme: ThemeData( primarySwatch: Colors.amber, ), home: SplashScreenPage(title: 'Nice splash page'), routes: routes, ); } }
pubspec.yaml
name: nice_animals description: A new Flutter application. version: 1.0.0+1 environment: sdk: ">=2.1.0 <3.0.0" dependencies: sqflite: flutter: sdk: flutter cupertino_icons: http: cached_network_image: ^1.1.3 dependency_overrides: http: dev_dependencies: flutter_test: sdk: flutter flutter: uses-material-design: true
The flutter tutorial is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application
For more information about Flutter. visit www.fluttertutorial.in