2017-06-10 110 views
1

我有一個類,calendar,它從一個文件異步讀取。如何等待類初始化?

// Copyright 2017 <Abhi Agarwal> 
// Refer to LICENSE 

// Dart Imports 
import 'dart:async'; 
import 'dart:convert'; 

// Flutter Imports 
import 'package:flutter/services.dart'; 

// Local Imports 
import 'event.dart'; 

/// Class deals with the school-wide calendar Calendar. 
class Calendar { 
    /// The days off in the year. 
    List<Event> daysOff = new List<Event>(); 

    /// The half-days, not necessarily days off. 
    List<Event> halfDays = new List<Event>(); 

    /// Vacations, extended days off. 
    List<Event> vactations = new List<Event>(); 

    DateTime schoolStart; 
    DateTime schoolEnd; 
    DateTime schoolMaxEnd; 

    Calendar() { 
    _addDaysOff(); 
    // _addHalfDays(); 
    // _addVacations(); 
    // _addTimes(); 
    } 

    static const String filePath = "assets/calendar/"; 

    /// Reads a JSON File specified by the Arguments and returns a Decoded Object. 
    Future<List<Map<String, String>>> _readJson(String fileName) async => 
     await JSON.decode(await rootBundle.loadString(filePath + fileName)); 

    Future _addDaysOff() async { 
    const String fileName = "days_off.json"; 
    final List<Map<String, String>> parsed = await _readJson(fileName); 

    for (final Map<String, String> item in parsed) { 
     Event event = new Event(item["name"], DateTime.parse(item["date"])); 
     daysOff.add(event); 
    } 
    } 
} 

這工作正常,但是當我想運行一個簡單的測試時出現問題。

// Copyright 2017 <Abhi Agarwal> 
// Refer to LICENSE 

import 'package:flutter/material.dart'; 

import 'definitions/calendar/calendar.dart'; 

void main() { 
    Calendar myCalendar = new Calendar(); 
    runApp(new Center(child: new Text(myCalendar.daysOff[0].name))); 
} 

隨着flutter run,我得到RangeError (index): Invalid value: Valid value range is empty: 0。這是有道理的,List在初始化時只有元素。問題是,我怎麼能在那裏放置一個佔位符,直到數據加載完畢?

回答

1

可以重構Calendar類暴露出Future即完成當Calendar準備使用:

// Private constructor, use create() to get an instance 
Calendar._(); 

// Future that completes when the new Calendar is ready to use 
static Future<Calendar> create() async { 
    Calendar calendar = Calendar._(); 
    await calendar._addDaysOff(); 
    // await calendar._addHalfDays(); 
    // await calendar._addVacations(); 
    // await calendar._addTimes(); 
    return calendar; 
} 

然後你可以awaitFuture,如:

main() async { 
    Calendar myCalendar = await Calendar.create(); 
    runApp(new Center(child: new Text(myCalendar.daysOff[0].name))); 
} 

你可以如果要將日曆實例化爲StatefulWidget某處,請等待Calendar使用FutureBuilder進行初始化先在你的Flutter小部件樹中播放,而不是讓它存在於根目錄下。

+0

謝謝!作爲一個主要使用C++的人,期貨是我不能饒舌的一個領域。 –