如何在 Flutter 中修复“类型‘_Type’不是类型 'FutureOr<Verse>'”的子类型
How to fix 'type '_Type' is not a subtype of type 'FutureOr<Verse>'' in Flutter
我正在编写一个 Flutter 应用程序,其中一个要求是离线保存数据以便在没有互联网的情况下读取它,但是当我从 Sqflite 的数据库加载时出现问题,我收到此错误:type '_Type' is not a subtype of type 'FutureOr<Verse>'
.我究竟做错了什么?我正在使用 BLOC 模式。
当我检查 res 变量形式的 getDailyVerse 函数时,我看到它是空的,但在 getAllVerse 中我看到我正在获取所有经文,但在 ListView 中我看不到是否加载。
这是我的模型:
import 'dart:async';
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:http/http.dart' show Client;
import 'dart:convert';
import '../models/verse.dart';
class VerseProvider {
VerseProvider._();
static final VerseProvider db = VerseProvider._();
Client client = Client();
final String _urlApi = "https://arcane-tundra-45231.herokuapp.com";
Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "DailyVerse.db");
return await openDatabase(
path,
version: 1,
onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE Verse ("
"id INTEGER PRIMARY KEY, "
"day INTEGER, "
"text TEXT, "
"text_es TEXT, "
"human_reference TEXT, "
"human_reference_es TEXT, "
"url TEXT, "
"url_es TEXT, "
"image_url TEXT"
")");
}
);
}
newVerse(Verse verse) async {
final db = await database;
// var res = await db.rawInsert(
// "INSERT INTO Verse (id, day, text, text_es, human_reference, human_reference_es, url, url_es, image_url)"
// " VALUES (${verse.id}, ${verse.day}, ${verse.text.replaceAll("'", "`")}, ${verse.textEs.replaceAll("'", "`")}, ${verse.humanReference.replaceAll("'", "`")}, ${verse.humanReferenceEs.replaceAll("'", "`")}, ${verse.url}, ${verse.urlEs}, ${verse.imageUrl})"
// );
var res = await db.insert(
"Verse",
verse.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace
);
return res;
}
Future<Verse> getDailyVerse() async {
final db = await database;
final today = DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays;
var res = await db.query("Verse", where: "day = ?", whereArgs: [today]);
print(res);
return res.isNotEmpty ? Verse.fromJson(res.first) : Null;
}
Future<VerseList> getAllVerse() async {
final db = await database;
var res = await db.query("Verse");
print(res);
return res.isNotEmpty ? VerseList.fromJson(res) : Null;
}
Future<Verse> fetchDailyVerse() async {
final response = await client.get(_urlApi + "/api/v0/verses/day");
print(response.body.toString());
print(DateTime.now());
print(DateTime.now());
print(DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays);
if (response.statusCode == 200) {
var jsonResponse = json.decode(response.body);
return Verse.fromJson(jsonResponse['data']);
} else {
throw Exception('Failed to Load Verse');
}
}
Future<VerseList> fetchAllVerses() async {
final response = await client.get(_urlApi + "/api/v0/verses/");
if (response.statusCode == 200) {
var jsonResponse = json.decode(response.body);
return VerseList.fromJson(jsonResponse['data']);
} else {
throw Exception('Failed to load Verses');
}
}
}
这是我在本地加载数据时调用它的时候:
import 'dart:async';
import '../resources/verse_provider.dart';
import '../models/verse.dart';
import '../resources/config_provider.dart';
class Repository {
final verseProvider = VerseProvider.db;
fetchDailyVerse() async {
bool isOfflineSaved = false;
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getDailyVerse();
} else {
return await verseProvider.fetchDailyVerse();
}
});
}
fetchAllVerses() async {
bool isOfflineSaved = false;
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getAllVerse();
} else {
return await verseProvider.fetchAllVerses();
}
});
}
}
这是我保存到本地时的样子:
Future saveVerseOffline() async {
// Show Dialog.waiting
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return new Dialog(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: [
new CircularProgressIndicator(),
new Text("Procesando..."),
],
),
);
},
);
// 1. Fetch the verses
final verses = fetchVerses();
print(verses);
// 2. Check if there any data saved
if (isDataSavedOnDB) {
// 3. If there are data. Do not save
new Future.delayed(new Duration(seconds: 2), () {
Navigator.pop(context); //pop dialog
});
} else {
print("something");
// 4. If there are not data. Begin to Save.
await verses.then((onValue) async {
int i = 0;
onValue.verses.forEach((f){
print("countiing $i");
// 5. Invocate the new verses and save it.
print(f);
VerseProvider.db.newVerse(f);
i += 1;
});
// 6. Dismmiss Dialog.
new Future.delayed(new Duration(seconds: 2), () {
Navigator.pop(context); //pop dialog
}).then((onValue) async {
await ConfigProvider().setSaveOffline(true).then((onValue){
setState((){
isDataSavedOnDB = true;
});
});
});
});
}
}
首先,我在调试代码,发现
final today = DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays;
它return0
- 我注意到这里:
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getAllVerse();
} else {
return await verseProvider.fetchAllVerses();
}
});
缺少 return,这导致没有渲染。我已经解决了:
return ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getAllVerse();
} else {
return await verseProvider.fetchAllVerses();
}
});
Future<VerseList> getAllVerse() async {
final db = await database;
var res = await db.query("Verse");
print(res);
return res.isNotEmpty ? VerseList.fromJson(res) : Null;
}
就像上面的方法一样,不能returnNull
,因为Null
不是VerseList
类型,应该改成Null
VerseList()
,或者您可以将 Future<VerseList>
更改为 Future<dynmic>
。
我正在编写一个 Flutter 应用程序,其中一个要求是离线保存数据以便在没有互联网的情况下读取它,但是当我从 Sqflite 的数据库加载时出现问题,我收到此错误:type '_Type' is not a subtype of type 'FutureOr<Verse>'
.我究竟做错了什么?我正在使用 BLOC 模式。
当我检查 res 变量形式的 getDailyVerse 函数时,我看到它是空的,但在 getAllVerse 中我看到我正在获取所有经文,但在 ListView 中我看不到是否加载。
这是我的模型:
import 'dart:async';
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:http/http.dart' show Client;
import 'dart:convert';
import '../models/verse.dart';
class VerseProvider {
VerseProvider._();
static final VerseProvider db = VerseProvider._();
Client client = Client();
final String _urlApi = "https://arcane-tundra-45231.herokuapp.com";
Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await initDB();
return _database;
}
initDB() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "DailyVerse.db");
return await openDatabase(
path,
version: 1,
onOpen: (db) {},
onCreate: (Database db, int version) async {
await db.execute("CREATE TABLE Verse ("
"id INTEGER PRIMARY KEY, "
"day INTEGER, "
"text TEXT, "
"text_es TEXT, "
"human_reference TEXT, "
"human_reference_es TEXT, "
"url TEXT, "
"url_es TEXT, "
"image_url TEXT"
")");
}
);
}
newVerse(Verse verse) async {
final db = await database;
// var res = await db.rawInsert(
// "INSERT INTO Verse (id, day, text, text_es, human_reference, human_reference_es, url, url_es, image_url)"
// " VALUES (${verse.id}, ${verse.day}, ${verse.text.replaceAll("'", "`")}, ${verse.textEs.replaceAll("'", "`")}, ${verse.humanReference.replaceAll("'", "`")}, ${verse.humanReferenceEs.replaceAll("'", "`")}, ${verse.url}, ${verse.urlEs}, ${verse.imageUrl})"
// );
var res = await db.insert(
"Verse",
verse.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace
);
return res;
}
Future<Verse> getDailyVerse() async {
final db = await database;
final today = DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays;
var res = await db.query("Verse", where: "day = ?", whereArgs: [today]);
print(res);
return res.isNotEmpty ? Verse.fromJson(res.first) : Null;
}
Future<VerseList> getAllVerse() async {
final db = await database;
var res = await db.query("Verse");
print(res);
return res.isNotEmpty ? VerseList.fromJson(res) : Null;
}
Future<Verse> fetchDailyVerse() async {
final response = await client.get(_urlApi + "/api/v0/verses/day");
print(response.body.toString());
print(DateTime.now());
print(DateTime.now());
print(DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays);
if (response.statusCode == 200) {
var jsonResponse = json.decode(response.body);
return Verse.fromJson(jsonResponse['data']);
} else {
throw Exception('Failed to Load Verse');
}
}
Future<VerseList> fetchAllVerses() async {
final response = await client.get(_urlApi + "/api/v0/verses/");
if (response.statusCode == 200) {
var jsonResponse = json.decode(response.body);
return VerseList.fromJson(jsonResponse['data']);
} else {
throw Exception('Failed to load Verses');
}
}
}
这是我在本地加载数据时调用它的时候:
import 'dart:async';
import '../resources/verse_provider.dart';
import '../models/verse.dart';
import '../resources/config_provider.dart';
class Repository {
final verseProvider = VerseProvider.db;
fetchDailyVerse() async {
bool isOfflineSaved = false;
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getDailyVerse();
} else {
return await verseProvider.fetchDailyVerse();
}
});
}
fetchAllVerses() async {
bool isOfflineSaved = false;
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getAllVerse();
} else {
return await verseProvider.fetchAllVerses();
}
});
}
}
这是我保存到本地时的样子:
Future saveVerseOffline() async {
// Show Dialog.waiting
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return new Dialog(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: [
new CircularProgressIndicator(),
new Text("Procesando..."),
],
),
);
},
);
// 1. Fetch the verses
final verses = fetchVerses();
print(verses);
// 2. Check if there any data saved
if (isDataSavedOnDB) {
// 3. If there are data. Do not save
new Future.delayed(new Duration(seconds: 2), () {
Navigator.pop(context); //pop dialog
});
} else {
print("something");
// 4. If there are not data. Begin to Save.
await verses.then((onValue) async {
int i = 0;
onValue.verses.forEach((f){
print("countiing $i");
// 5. Invocate the new verses and save it.
print(f);
VerseProvider.db.newVerse(f);
i += 1;
});
// 6. Dismmiss Dialog.
new Future.delayed(new Duration(seconds: 2), () {
Navigator.pop(context); //pop dialog
}).then((onValue) async {
await ConfigProvider().setSaveOffline(true).then((onValue){
setState((){
isDataSavedOnDB = true;
});
});
});
});
}
}
首先,我在调试代码,发现
final today = DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays;
它return0
- 我注意到这里:
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getAllVerse();
} else {
return await verseProvider.fetchAllVerses();
}
});
缺少 return,这导致没有渲染。我已经解决了:
return ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
if (isOfflineSaved) {
return await verseProvider.getAllVerse();
} else {
return await verseProvider.fetchAllVerses();
}
});
Future<VerseList> getAllVerse() async {
final db = await database;
var res = await db.query("Verse");
print(res);
return res.isNotEmpty ? VerseList.fromJson(res) : Null;
}
就像上面的方法一样,不能returnNull
,因为Null
不是VerseList
类型,应该改成Null
VerseList()
,或者您可以将 Future<VerseList>
更改为 Future<dynmic>
。