Giter Club home page Giter Club logo

Comments (8)

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

First of all, @letsar has created this package, I have taken over the maintenance since 2 weeks. So all the credits go to him.

For your question:

Floor has a floor_generator that generates the non abstract class. If you want to register the abstract class you will have to register an instance that comes from the generated database.

Personally, I have never used floor but by reading the readme on pub.dev I think that is the way to go.

I use moor because it generates the dao classes in a separate file and the dao needs a database. So that will be injected with kiwi as well.

I will have some spare time on Thursday so I will play around with Floor and I will let you know what the best sollution is.

from kiwi.

jaydangar avatar jaydangar commented on August 29, 2024

@vanlooverenkoen Thanks, It's okay to use Repository class as a singleton? because repository class contains objects which provides access to API and Database. So, by making Repository class singleton, we will be using a repository and related API and DB as a singleton too. Do I understood this part correct? kindly express your views on it.

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

Yes indeed. We usually do it like this

Singleton repo's
Singleton services (apis)
Singleton dao's
Singleton database
Factories viewmodels

On top of that every Singleton ia registered as an abstract class. So it is easier to write automated tests

from kiwi.

jaydangar avatar jaydangar commented on August 29, 2024

@vanlooverenkoen So, Database class and Dao's in floor are implemented as abstract class only? so does that mean it's singleton by default?

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

No that does not mean it is a singleton by default. (Im not sure what the correct implementation is for floor. But I would think it is just a normal object. By using kiwi you can make sure the instance is always a singleton. Because kiwi maintains that for you.

from kiwi.

jaydangar avatar jaydangar commented on August 29, 2024

@vanlooverenkoen Kindly let me know if there's any way to do it using abstract class, I did't have any example for it. A big thanks in advance.

from kiwi.

jaydangar avatar jaydangar commented on August 29, 2024

Hello @vanlooverenkoen, I have give your advice a shot and look into generated floor file, which is as below.

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'cookdb.dart';

// **************************************************************************
// FloorGenerator
// **************************************************************************

class $FloorCookDataBase {
  /// Creates a database builder for a persistent database.
  /// Once a database is built, you should keep a reference to it and re-use it.
  **static _$CookDataBaseBuilder databaseBuilder(String name) =>
      _$CookDataBaseBuilder(name);**

  /// Creates a database builder for an in memory database.
  /// Information stored in an in memory database disappears when the process is killed.
  /// Once a database is built, you should keep a reference to it and re-use it.
  static _$CookDataBaseBuilder inMemoryDatabaseBuilder() =>
      _$CookDataBaseBuilder(null);
}

class _$CookDataBaseBuilder {
  _$CookDataBaseBuilder(this.name);

  final String name;

  final List<Migration> _migrations = [];

  Callback _callback;

  /// Adds migrations to the builder.
  _$CookDataBaseBuilder addMigrations(List<Migration> migrations) {
    _migrations.addAll(migrations);
    return this;
  }

  /// Adds a database [Callback] to the builder.
  _$CookDataBaseBuilder addCallback(Callback callback) {
    _callback = callback;
    return this;
  }

  /// Creates the database and initializes it.
  Future<CookDataBase> build() async {
    final path = name != null
        ? await sqfliteDatabaseFactory.getDatabasePath(name)
        : ':memory:';
    final database = _$CookDataBase();
    database.database = await database.open(
      path,
      _migrations,
      _callback,
    );
    return database;
  }
}

class _$CookDataBase extends CookDataBase {
  _$CookDataBase([StreamController<String> listener]) {
    changeListener = listener ?? StreamController<String>.broadcast();
  }

  CookDAO _cookDAOInstance;

  Future<sqflite.Database> open(String path, List<Migration> migrations,
      [Callback callback]) async {
    final databaseOptions = sqflite.OpenDatabaseOptions(
      version: 1,
      onConfigure: (database) async {
        await database.execute('PRAGMA foreign_keys = ON');
      },
      onOpen: (database) async {
        await callback?.onOpen?.call(database);
      },
      onUpgrade: (database, startVersion, endVersion) async {
        await MigrationAdapter.runMigrations(
            database, startVersion, endVersion, migrations);

        await callback?.onUpgrade?.call(database, startVersion, endVersion);
      },
      onCreate: (database, version) async {
        await database.execute(
            'CREATE TABLE IF NOT EXISTS `Cook` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `cookName` TEXT, `gender` TEXT, `experience` INTEGER, `language` TEXT, `perMonthCharge` INTEGER, `rating` REAL)');

        await callback?.onCreate?.call(database, version);
      },
    );
    return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions);
  }

  @override
  CookDAO get cookDAO {
    return _cookDAOInstance ??= _$CookDAO(database, changeListener);
  }
}

class _$CookDAO extends CookDAO {
  _$CookDAO(this.database, this.changeListener)
      : _queryAdapter = QueryAdapter(database),
        _cookInsertionAdapter = InsertionAdapter(
            database,
            'Cook',
            (Cook item) => <String, dynamic>{
                  'id': item.id,
                  'cookName': item.cookName,
                  'gender': item.gender,
                  'experience': item.experience,
                  'language': item.language,
                  'perMonthCharge': item.perMonthCharge,
                  'rating': item.rating
                });

  final sqflite.DatabaseExecutor database;

  final StreamController<String> changeListener;

  final QueryAdapter _queryAdapter;

  static final _cookMapper = (Map<String, dynamic> row) => Cook(
      row['id'] as int,
      row['cookName'] as String,
      row['gender'] as String,
      row['experience'] as int,
      row['language'] as String,
      row['perMonthCharge'] as int,
      row['rating'] as double);

  final InsertionAdapter<Cook> _cookInsertionAdapter;

  @override
  Future<List<Cook>> fetchAllCooks() async {
    return _queryAdapter.queryList('Select * from Cook', mapper: _cookMapper);
  }

  @override
  Future<void> insertCooks(List<Cook> cook) async {
    await _cookInsertionAdapter.insertList(cook, OnConflictStrategy.replace);
  }
}

Now in my main function, I have create singleton Object by following.


main(List<String> args) {
  KiwiContainer kiwiContainer = KiwiContainer();
  kiwiContainer.registerSingleton((container) => Repository());
  kiwiContainer.registerSingleton((container) => APIProvider());
  **kiwiContainer.registerSingleton((container) async {
    return await $FloorCookDataBase.databaseBuilder('cook_db.db').build();
  });
  kiwiContainer.registerSingleton((container)=>KiwiContainer().resolve<CookDataBase>().cookDAO);**  
  runApp(MainPage());
}

@vanlooverenkoen can you kindly tell me if my approach is right or not? I am accessing DataBase class through builder and using that singleton Database Object I am accessing DAO object which is defined as a class in CookDataBase abstract class. like following :

@Database(version: 1, entities: [Cook])
abstract class CookDataBase extends FloorDatabase {
  CookDAO get cookDAO;
}

from kiwi.

vanlooverenkoen avatar vanlooverenkoen commented on August 29, 2024

@jaydangar I'm sorry that it took so long. I completely forgot about this ticket. I would do the following

Future<void> main(List<String> args) async{
 await setupDi();
  runApp(MainPage());
}

Future<void> setupDi(){
  KiwiContainer().registerSingleton((container) => Repository());
  KiwiContainer().registerSingleton((container) => APIProvider());
  final db = await $FloorCookDataBase.databaseBuilder('cook_db.db').build()
  KiwiContainer().registerSingleton((container) => db);
  KiwiContainer().registerSingleton((container)=> KiwiContainer().resolve<CookDataBase>().cookDAO);
}

Using the kiwi_generator will result in some extra boilerplate code, that is because of how floor is setup.
Your personDao

import 'package:floor/floor.dart';
import 'package:kiwi_floor/db/database.dart';
import 'package:kiwi_floor/models/person.dart';

@dao
abstract class PersonDao {
  factory PersonDao.fromDb(AppDatabase db) => db.personDao;  //the extra boilerplate code

  @Query('SELECT * FROM Person')
  Future<List<Person>> findAllPersons();

  @Query('SELECT * FROM Person WHERE id = :id')
  Stream<Person> findPersonById(int id);

  @insert
  Future<void> insertPerson(Person person);
}

And your injector file will look like this:

abstract class Injector {
  Future<void> configure() async {
    final db = await $FloorCookDataBase.databaseBuilder('cook_db.db').build()
    KiwiContainer().registerSingleton((container) => db);
    registerDao();
  }

  @Register.singleton(PersonDao, constructorName: 'fromDb') //consturctorName is extra boilerplate code to use with floor
  void registerDao();
}

I personally use Moor for my db integration. It works way better with kiwi. Because the implementation of moor is better for dependency injection.

I hope this answers your question. Sorry for the late response.

from kiwi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.