如何在Flutter中修复'type'_Type'不是'FutureOr <verse>''类型的子类型

时间:2019-03-31 21:08:35

标签: dart flutter sqflite

我正在编写Flutter App,其中一项要求是脱机保存数据以在不使用互联网的情况下进行读取,但是当我从Sqflite的数据库加载时出现问题,我遇到了此错误:type '_Type' is not a subtype of type 'FutureOr<Verse>'。我究竟做错了什么?我正在使用BLOC模式。

当我从getDailyVerse函数中检查res变量时,我看到的是空的,但是在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;
            });
          });
        });
      });
    }
  }

2 个答案:

答案 0 :(得分:0)

首先,我正在调试代码,然后发现

final today = DateTime(DateTime.now().year, 1, 1, 0,).difference(DateTime(DateTime.now().year, 1, 1, 0, 0)).inDays;

返回0

  1. 我在这里注意:
ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
     if (isOfflineSaved) {
      return await verseProvider.getAllVerse();
    } else {
      return await verseProvider.fetchAllVerses();
    }
   });

缺少返回值,这不会导致任何渲染。我已经解决了:

return ConfigProvider().getSaveOffline().then((value) => isOfflineSaved = value ).then((onValue) async {
     if (isOfflineSaved) {
      return await verseProvider.getAllVerse();
    } else {
      return await verseProvider.fetchAllVerses();
    }
   });

答案 1 :(得分:0)

Future<VerseList> getAllVerse() async {
    final db = await database;

    var res = await db.query("Verse");

    print(res);

    return res.isNotEmpty ? VerseList.fromJson(res) : Null;
  }

就像上面的方法一样,您不能返回Null,因为Null不是VerseList类型,您应该将Null更改为VerseList() ,也可以将Future<VerseList>更改为Future<dynmic>