Flutter在创建对象时运行异步操作

时间:2019-02-06 16:16:46

标签: api asynchronous dart flutter

我是新手,我知道这是一个非常基本的问题,但是我已经坚持了三天。我只想从创建对象的API中获取数据。当您运行代码时,它将引发异常,但是当您热重新加载它时,异步操作将开始正常工作。请告诉我我错了。我自己做了一些额外的类,尽管应该避免使用这种方法进行编码。

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main(){
    runApp(
       MaterialApp(
        title : "Quake",
        home :  HomePage()
      )
    );
}
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
    dataRepository.init();
  }
  @override
  Widget build(BuildContext context) {
    return Reading();
  }
}
class Reading extends StatefulWidget {
  @override
  _ReadingState createState() => _ReadingState();
}
class _ReadingState extends State<Reading> {
  Map _data = Map();
  List _features = List();
  @override
  void initState() {
    super.initState();
    _data = dataRepository.getReading();
    _features = _data['features'];
  }
  @override
  Widget build(BuildContext context) {
    return  Scaffold(
        appBar:  AppBar(
          title:  Text("Quake"),
          centerTitle: true,
          backgroundColor: Colors.black,
        ),
        body :  Center(
            child :  ListView.builder(
              itemCount: _features.length,
              padding: const EdgeInsets.all(14.5),
              itemBuilder: (BuildContext context, int position){
                var format =  DateFormat.yMMMd("en_US").add_jm();
                var _date = format.format( DateTime.fromMicrosecondsSinceEpoch(_features[position]['properties']['time']*1000, isUtc: true));
                return  Column(
                  children: <Widget>[
                    Divider(height : 5.5),
                    ListTile(
                      title:  Text("$_date",
                          style:  TextStyle(fontSize: 16.0)),
                      subtitle:  Text("${_features[position]['properties']['place']}",
                          style:  TextStyle(fontSize: 13.0)),
                      leading:  CircleAvatar(
                          backgroundColor : Colors.black,
                          child :  Text("${_features[position]['properties']['mag']}", style:  TextStyle( color: Colors.white))
                      ),
                      onTap: () => _windowOnTapping(context, _features[position]['properties']['title']),
            )],);},)));}}

Future _windowOnTapping(BuildContext context, String message){
  var alert =  AlertDialog(
    title:  Text("Quakes"),
    content:  Text(message),
    actions: <Widget>[
      FlatButton ( child:  Text("OK"), onPressed: (){ Navigator.pop(context);})
    ],
  );
  showDialog( context: context, builder: (context)=> alert);
}
final DataRepository dataRepository = DataRepository._private();
class DataRepository{
  DataRepository._private();
  Map _data;
  void init() async{
    String apiUrl = 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson';
    http.Response response = await http.get(apiUrl);
    _data = json.decode(response.body);
  }
  Map getReading(){
    return _data;
  }
}

1 个答案:

答案 0 :(得分:0)

使用FutureBuilder读取Future并仅在组件返回后才进行渲染,如下所示:

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() {
  runApp(MaterialApp(title: "Quake", home: HomePage()));
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Reading();
  }
}

class Reading extends StatefulWidget {
  @override
  _ReadingState createState() => _ReadingState();
}

class _ReadingState extends State<Reading> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Quake"),
          centerTitle: true,
          backgroundColor: Colors.black,
        ),
        body: FutureBuilder<Map>(
            future: dataRepository.getReading(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                var features = snapshot.data['features'];
                return Center(
                    child: ListView.builder(
                  itemCount: features.length,
                  padding: const EdgeInsets.all(14.5),
                  itemBuilder: (BuildContext context, int position) {
                    var format = DateFormat.yMMMd("en_US").add_jm();
                    var _date = format.format(
                        DateTime.fromMicrosecondsSinceEpoch(
                            features[position]['properties']['time'] * 1000,
                            isUtc: true));
                    return Column(
                      children: <Widget>[
                        Divider(height: 5.5),
                        ListTile(
                          title:
                              Text("$_date", style: TextStyle(fontSize: 16.0)),
                          subtitle: Text(
                              "${features[position]['properties']['place']}",
                              style: TextStyle(fontSize: 13.0)),
                          leading: CircleAvatar(
                              backgroundColor: Colors.black,
                              child: Text(
                                  "${features[position]['properties']['mag']}",
                                  style: TextStyle(color: Colors.white))),
                          onTap: () => _windowOnTapping(context,
                              features[position]['properties']['title']),
                        )
                      ],
                    );
                  },
                ));
              } else {
                return Text("Loading");
              }
            }));
  }
}

Future _windowOnTapping(BuildContext context, String message) {
  var alert = AlertDialog(
    title: Text("Quakes"),
    content: Text(message),
    actions: <Widget>[
      FlatButton(
          child: Text("OK"),
          onPressed: () {
            Navigator.pop(context);
          })
    ],
  );
  showDialog(context: context, builder: (context) => alert);
}

final DataRepository dataRepository = DataRepository._private();

class DataRepository {
  DataRepository._private();

  Future<Map> getReading() async {
    String apiUrl =
        'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson';
    http.Response response = await http.get(apiUrl);
    var data = json.decode(response.body);
    print(data);
    return data;
  }
}