Модели Flutter Sqflite для нескольких столов - PullRequest
0 голосов
/ 05 декабря 2018

Я прошел много уроков и примеров о том, как реализовать Sqflite во Flutter.Все остальные примеры выполняются с использованием только одной модели или таблицы базы данных.Как определено в этих уроках:

https://pub.dartlang.org/packages/sqflite

https://www.developerlibs.com/2018/07/flutter-sqlite-database-example.html

http://camposha.info/flutter/sqflite-insert-select-show

Насколько я понял, нам нужносоздайте столько моделей и помощников, сколько есть таблиц.Для каждой таблицы базы данных будет файл model.dart и файл helper.dart.

Мой вопрос здесь, есть ли способ, которым я могу иметь только один помощник для всех моделей?

ОБНОВЛЕНИЕ

В файле helper.dart есть будущая "вставка".Как я могу использовать одну и ту же вставку в будущем для всех моделей?

Future<Todo> insert(Todo todo) async {
    todo.id = await db.insert(tableTodo, todo.toMap());
    return todo;
}

1 Ответ

0 голосов
/ 06 декабря 2018

Я сделал несколько комментариев, советовавших об обратном, но я только что вспомнил, что в моем последнем проекте я делал что-то подобное, это было для База данных Firebase , но это было бы очень похоже на sqflite .

Я создал BaseItem абстрактный класс с key, и все модели будут наследоваться от него.

Я также создал BaseProvider абстрактный класс, который будеттребует BaseItem и определяет простые методы для доступа к модели.

Методы upsert и delete лежат в FirebaseBaseProvider, что расширяет BaseProvider.

Я будувставьте его части сюда (удалив довольно много, чтобы сделать его более понятным):

abstract class BaseItem {
  const BaseItem({this.key});
  final String key;
}

abstract class BaseProvider<T extends BaseItem> {
  Future<List<T>> find();

  Future<BaseKey> upsert(T item);

  Future<int> delete(T item);
}


abstract class FirebaseBaseProvider<T extends BaseItem> {
  // Abstract methods which need to be implemented
  T fromMap(BaseKey key, dynamic map);
  Map<String, dynamic> toJson(BaseKey key, T item);

  Future<DatabaseReference> getReference(BaseKey base) async { ... }    
  BaseKey compileKey(T item, {String useKey}) { ... }

  Future<List<T>> find() async {
    List<T> result = new List();
    // my implementation doesnt work like this, 
    // as it's firebase based, but this would
    // be the place in a Sqflite implementation to use
    // fromMap and load the items
    return result;
  }

  Future<BaseKey> upsert(T item) async {
    if (item == null) return null;

    BaseKey key = compileKey(item);
    (await getReference(key)).set(toJson(key, item));
    return key;
  }

  Future<int> delete(T item) async {
    if (item == null) return null;

    if (item.key != null && item.key != "") {
      (await getReference(compileKey(item))).remove();
    }
    return 0;
  }
}

Затем, чтобы реализовать модель News или любую другую модель, я бы создал ее простоопределяя его содержимое следующим образом:

class News extends BaseItem {
  News({String key, this.creation, this.messageSubject, this.messageBody}) : super(key: key);

  final DateTime creation;
  final String messageSubject;
  final String messageBody;

  bool operator ==(o) => o is News && (o.key == key);
  int get hashCode => key.hashCode;
}

И для этого потребуется специальный поставщик, который будет реализовывать только методы toJson и fromMap, например:

class NewsProvider extends FirebaseBaseProvider<News> {
  @override
  Map<String, dynamic> toJson(BaseKey key, News news) {
    return {
      "creation": news.creation,
      "messageSubject": news.messageSubject,
      "messageBody": news.messageBody,
    };
  }

  @override
  News fromMap(BaseKey key, dynamic map) {
    DateTime creation = map["creation"] == null ? null : DateTime.tryParse(map["creation"] as String);

    return new News(
      key: key.child.key,
      creation: creation,
      messageSubject: map["messageSubject"] as String,
      messageBody: map["messageBody"] as String,
    );
  }
}

В конце концов, NewProvider предоставляет метод find, upsert и deleteds, но их реализация лежит на абстрактном классе, только одна их реализация для всех моделей, как вы и хотели.

Конечно, моя реализация более сложна, чем обе, потому что Firebase требует другого подходадля получения / загрузки элементов, а также в результате того, что метод find должен быть разным в каждой конкретной модели поставщика.Но, тем не менее, многое можно упростить.

Что я говорил в комментарии, так это то, что этот последний класс, специфические NewsProvider, которые имеют как toJson, так и fromMap конкретные реализации, также могут быть обобщеныиспользуя аннотации в классе модели News, но это приносит много проблем и неясности и - на мой взгляд, конечно - это того не стоит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...