如何等待Class初始化?

时间:2017-06-10 20:36:00

标签: flutter

我有一个类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只在初始化时才有元素。问题是,如何在数据加载之前放置占位符?

2 个答案:

答案 0 :(得分:4)

您可以重构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;
}

然后你可以await Future,例如:

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

如果您希望在Flutter窗口小部件树中更深处的Calendar实例化日历,而不是让它存在,则可以等待StatefulWidget使用FutureBuilder进行初始化根。

答案 1 :(得分:0)

Collin Jackson 的回答对我帮助很大,但我花了一些时间来理解上下文,以便根据我的需要实施它。下面是一个更通用的示例,它使用 package com.chubb; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mongodb.MongoDbConstants; import org.apache.tomcat.util.json.JSONParser; import org.bson.Document; import org.bson.conversions.Bson; import org.json.JSONArray; import org.json.JSONObject; //import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Flow.Publisher; import java.util.LinkedHashMap; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.apache.camel.LoggingLevel; import org.apache.camel.ProducerTemplate; //import org.apache.camel.component.mongodb3.MongoDbConstants; //import com.mongodb.MongoClient; //import com.mongodb.MongoClientURI; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; //import org.json.JSONObject; /** * A example hellow world Camel route */ @Component public class RenewalRegistryRoute extends RouteBuilder { String KafkaOffNumber; String mongoOffNumber; JSONObject arry; JSONObject arry5; JSONObject listJson; JSONArray arry2; JSONObject arry3= new JSONObject(); String renewalOffer; Bson combine; Bson filterField; Bson[] bodyList; String resultListStr; List<String> resultList; String mongoPolicyRenewalState; String kafkaPolicyRenewalState; Bson msg; Bson msg1; String filterField2; @Override public void configure() throws Exception { from("kafka:{{kafkaTopics}}?brokers={{kafkaBroker}}" + "&groupId={{TopicGroupID}}" + "&sslTruststoreLocation={{sslTruststoreLocation}}" + "&sslTruststorePassword={{sslTruststorePassword}}" + "&securityProtocol={{securityProtocol}}" + "&saslMechanism={{saslMechanism}}" + "&sslKeyPassword={{sslKeyPassword}}" + "&saslJaasConfig={{saslJaasConfig}} username=\"testuser1\" password=\"testuser1\";") .log("kafka broker----------- {kafkaBroker} and {{kafkaBroker}}") .log("Bodyyyyyy ${body} Headers ${headers}").process(ex -> { Bson firstCond = null; Bson secondCond = null; String json = ex.getIn().getBody(String.class); arry = new JSONObject(json); renewalOffer = arry.getJSONObject("sourceSystemData").getString("offeringNumber"); System.out.println("********* renewalOffer:"+renewalOffer); ex.getIn().setHeader("renewalOffern", renewalOffer); }).log("header is = ${header.renewalOffern} ") .setHeader(MongoDbConstants.CRITERIA, new Expression() { public <T> T evaluate(Exchange exchange, Class<T> type) { String renewalOffer = exchange.getIn().getHeader("renewalOffern", String.class); System.out.println("********* Inside Evaluate renewalOffer: "+renewalOffer); Bson equalsClause = Filters.eq("sourceSystemData.offeringNumber", renewalOffer); System.out.println("*************equalsClause: "+equalsClause); return exchange.getContext().getTypeConverter().convertTo(type, equalsClause); }; }) //.setHeader(MongoDbConstants.BATCH_SIZE, constant(10)) .to("mongodb:mongoClientConnectionBean?database=renewalRegistryDB&collection=renewalShell&operation=findAll") .marshal().json(true).process(ex -> { resultListStr = ex.getIn().getBody(String.class); ex.getIn().setHeader("resultListS", resultListStr); }) .choice() .when(header("resultListS").isEqualTo("")) .to("mongodb:mongoClientConnectionBean?database=renewalRegistryDB&collection=renewalShell&operation=insert") .otherwise() .process(ex -> { String resultListStr2=ex.getIn().getHeader("resultListS",String.class); arry2 = new JSONArray(resultListStr2); resultList = new ArrayList<String>(); for (int i = 0; i < arry2.length(); i++) { resultList.add(arry2.get(i).toString()); } ex.getIn().setHeader("result", resultList); }) .loop(simple("${headers.result.size}")) .process(ex->{ List<String> list = ex.getIn().getHeader("result", List.class); String renewalRegistryMongodata = list.get(0); listJson = new JSONObject(renewalRegistryMongodata); mongoOffNumber= listJson.getJSONObject("sourceSystemData").getString("offeringNumber"); mongoPolicyRenewalState= listJson.getJSONObject("renewalInformation").getString("policyRenewalState"); String mongoPolicyRenewalStatus= listJson.getJSONObject("renewalInformation").getString("policyRenewalStatus"); String kafkaOffNumber = arry.getJSONObject("sourceSystemData").getString("offeringNumber"); kafkaPolicyRenewalState = arry.getJSONObject("renewalInformation").getString("policyRenewalState"); String kafkaPolicyRenewalStatus = arry.getJSONObject("renewalInformation").getString("policyRenewalStatus"); filterField = Filters.eq("sourceSystemData.offeringNumber", kafkaOffNumber); filterField2= filterField.toString(); if(mongoPolicyRenewalState!=kafkaPolicyRenewalState) { msg = Updates.set("renewalInformation.policyRenewalState", "CREATED3"); if(mongoPolicyRenewalStatus!=kafkaPolicyRenewalStatus) { msg1 = Updates.set("renewalInformation.policyRenewalStatus", "SUCESS3"); } combine = Updates.combine(msg, msg1); from("direct:update").log("Writing to mongoDB").log("Before inserting to MongoDB") .setBody(constant(combine)).log("The body is ${body}") .setHeader(MongoDbConstants.CRITERIA, constant(filterField)) // .setHeader(MongoDbConstants.MULTIUPDATE, constant(true)) .removeHeaders(filterField2) .to("mongodb:mongoClientConnectionBean?database=renewalRegistryDB&collection=renewalShell&operation=update") .log("The returned Data is ${body} "); }); } } ,正如 Collin 建议的那样,并且可以直接在 DartPad 中运行。

FutureBuilder