Flutterで最初のアプリを作成しています。このアプリは_sqlite database
_を使用しています。モデルとリポジトリがあります。
コードレイアウト:
私には2つのモデルがあります(完成したアプリにはさらに多くあります)UserModel
、TimesheetModel
、これらは両方ともBaseModel
を拡張します
私は2つのリポジトリを持っています(完成したアプリではさらに多くなります)UserRepository
、TimesheetRepository
、これらは両方ともBaseRepository
を拡張します
私がやろうとしていること:BaseRepository
内のgetAll()
、countAll()
などの再利用可能なコードを使用して、すべてのリポジトリを拡張します。ベースリポジトリにはこの機能があり、テーブル名を設定して返されるModel
を設定するだけで済みます。
エラー:BaseRepository
がBaseModel
タイプを返しているため、コードからわかるように、タイムシートオブジェクトでall()
関数を呼び出すと、次のエラーが発生します。 :タイプ 'List'はタイプ 'List'のサブタイプではありません
これを修正する方法がわかりません。何か提案がありますか?
BaseRepository
_abstract class BaseRepository {
final String table;
final model;
BaseRepository({this.table, this.model});
// Retrieve all the items
Future<List<BaseModel>> all() async {
final sql = '''SELECT * FROM $table''';
final data = await db.rawQuery(sql);
List<BaseModel> forms = List();
for (final node in data) {
final form = model.fromJson(jsonData: node);
forms.add(form);
}
return forms;
}
// Find an item by its ID
Future findById(int id) async {
final sql = '''SELECT * FROM $table
WHERE id = ?''';
List<dynamic> params = [id];
final data = await db.rawQuery(sql, params);
final form = model.fromJson(jsonData: data.first);
return form;
}
// Count all the items
Future<int> count() async {
final data = await db.rawQuery('''SELECT COUNT(*) FROM $table''');
int count = data[0].values.elementAt(0);
int idForNewItem = count++;
return idForNewItem;
}
// clear the table
Future<void> delete() async {
// truncate current database table
await db.rawQuery('''DELETE FROM $table''');
}
}
_
TimesheetRepository
_class TimesheetRepository extends BaseRepository {
String table = 'timesheets';
TimesheetModel model = new TimesheetModel();
// Search for a item by its name
Future<List<TimesheetModel>> findByDate(DateTime dateTime) async {
final String date = DateFormat("yyyy-MM-dd").format(dateTime);
final sql = '''SELECT * FROM $table WHERE timesheet_date = ?''';
List<dynamic> params = [date];
final data = await db.rawQuery(sql, params);
List<TimesheetModel> forms = List();
for (final node in data) {
final form = TimesheetModel.fromJson(jsonData: node);
forms.add(form);
}
return forms;
}
// Add a new item
Future<void> store(TimesheetModel timesheet) async {
final sql = '''INSERT INTO $table
(
user_id,
timesheet_date,
start_time,
end_time,
json,
is_uploaded
)
VALUES (?,?,?,?,?,?)''';
List<dynamic> params = [
timesheet.userId,
DateFormat("yyyy-MM-dd").format(timesheet.timesheetDate),
timesheet.startTime,
timesheet.endTime,
convert.json.encode(timesheet.json),
timesheet.is_uploaded,
];
final result = await db.rawInsert(sql, params);
DatabaseCreator.databaseLog('Add form', sql, null, result, params);
}
}
_
タイムシートで全員を呼び出すとき
_TimesheetRepository timesheet = TimesheetRepository();
timesheet.all();
_
基本モデル
_abstract class BaseModel {
fromJson();
}
_
タイムシートモデル
_
class TimesheetModel extends BaseModel {
int id;
int userId;
DateTime timesheetDate;
String startTime;
String endTime;
Map json = {
"task": "",
"detail": "",
"notes": "",
};
bool is_uploaded;
TimesheetModel({
this.id,
this.userId,
this.timesheetDate,
this.startTime,
this.endTime,
this.json,
this.is_uploaded,
});
fromJson({Map<String, dynamic> jsonData}) {
return TimesheetModel(
id: jsonData['id'] as int,
userId: jsonData['user_id'] as int,
timesheetDate: timesheetDate,
startTime: jsonData['start_time'],
endTime: jsonData['end_time'],
is_uploaded: hasUploaded,
);
}
}
_
同じオブジェクトの有効なインスタンスを作成できるようにするには、モデルの空のインスタンスを渡す必要があるので、私が行っている方法でのfromJsonの解析は行いません。ただし、アーキテクチャを機能させるには、いくつかの修正を行う必要があります。
1-ジェネリックを使用します。
BaseRepository
abstract class BaseRepository<T extends BaseModel> {
BaseRepository({this.table, this.model});
final String table;
final T model;
// Retrieve all the items
Future<List<T>> all() async {
final sql = '''SELECT * FROM $table''';
final data = await db.rawQuery(sql);
return data.map((node) {
return model.fromJson(jsonData: node);
}).toList();
}
Future<T> findById(int id) async {
final sql = '''SELECT * FROM $table
WHERE id = ?''';
final data = await db.rawQuery(sql, [id]);
return model.fromJson(jsonData: data.first);
}
// Count all the items
Future<int> count() async {
final data = await db.rawQuery('''SELECT COUNT(*) FROM $table''');
int count = data[0].values.elementAt(0);
int idForNewItem = count++;
return idForNewItem;
}
// clear the table
Future<void> delete() async {
// truncate current database table
await db.rawQuery('''DELETE FROM $table''');
}
}
2-スーパーコンストラクターを正しく呼び出す
TimesheetRepository
class TimesheetRepository extends BaseRepository<TimesheetModel> {
///IMHO you should not pass TimesheetModel instance here, it is really redundant
///you can create a parse class that receives the type and a json and does the
///trick
TimesheetRepository() : super(table: 'timesheets', model: TimesheetModel());
}
3-fromJson
メソッドに正しいリターンを追加する
abstract class BaseModel {
BaseModel fromJson({Map<String, dynamic> jsonData});
}
データベースと統合してテストできなかったので、動作するかどうかをお知らせください。
このようなallメソッドを作成した場合、 Dartがタイプを推測するには、このタイプの情報が必要だと思います。よくわからないけど
Future<List<T extends BaseModel>> all() async {