Flutter local database nice animal

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 :

Flutter local database nice animal

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