从异步调用填充的Flutter列表会引发应用内错误,但不会崩溃

时间:2019-08-07 19:51:20

标签: android asynchronous flutter

我有一个清单是从有状态窗口小部件的异步调用中填充的。它获取列表的第一项(实际上应该只是一项),并将其内容显示在卡中。

当我导航到屏幕时,它说没有元素与[0]的红色大屏幕相遇,但是屏幕几乎立即消失了(约0.5秒)。我假设这意味着呼叫正在完成,错误消失了。但是,这会在用户随机看到错误时带来非常差的用户体验。

我尝试在构建之前将异步调用放入init方法中-但是,错误仍在发生。

响应页面:

import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:location/location.dart';
import 'package:marketapp/Areas/Meet/MeetDetailsPage.dart';

class ResponsePage extends StatefulWidget {
  static const int = 5;
  static const routeName = '/responsepage';
  final ResponsePageArguments rpa;

  ResponsePage({Key key, @required this.rpa}) : super(key: key);

  // Create initial state of the Meet Page
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ResponsePageState();
  }
}

class ResponsePageState extends State<ResponsePage> {
  Location location = Location();
  LocationData currentLocation;
  var isLoading = false;
  var id;
  var meets = new List<MeetModel>();

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    final _formKey = GlobalKey<FormState>();
    return Form(
        key: _formKey,
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Card(
                  child: ListTile(
                title: Text(meets[0].host + " wants to meet you!"),
                subtitle: Text("Requested at " + meets[0].requestTime),
              )),
              Padding(
                  padding: const EdgeInsets.symmetric(
                      vertical: 10.0, horizontal: 5.0),
                  child: Row(children: <Widget>[
                    RaisedButton(
                        onPressed: () {
                          declineRequest(id);
                        },
                        child: Text('Decline')),
                    RaisedButton(
                      onPressed: () {
                        // Validate returns true if the form is valid, false otherwise
                        acceptRequest(id);
                      },
                      child: Text('Accept'),
                    ),
                  ]))
            ]));
  }

  @override
  initState() {
    getMeet(widget.rpa.id);
    id = widget.rpa.id;
    super.initState();
    location.onLocationChanged().listen((value) {
      if (this.mounted) {
        setState(() {
          currentLocation = value;
        });
      }
    });
  }

  acceptRequest(id) async {
    setState(() {
      isLoading = true;
    });
    final url = 'https://.azurewebsites.net/Meets/MeetResponse/$id';
    var userToken = await getToken();
    print("Token printed " + userToken.toString());
    var body = jsonEncode({'latitude': currentLocation.latitude.toString(),
      'longitude' : currentLocation.longitude.toString()});
    print("Current Latitude: " + currentLocation.latitude.toString());
    print("Current Longitude: " + currentLocation.longitude.toString());

    /*final responseBody = (await http.get(
            'https://.azurewebsites.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
        .body;*/
    /*return */
    http.post(
      url,
      headers: {
        "Content-Type": "application/json",
        "Authorization": "Bearer $userToken"
      },
      body: body
    ).then((http.Response response) {
      print("Accept Response Status: ${response.statusCode}");
      print("Accept Response Body: ${response.body}");
      setState(() {
        isLoading = false;
      });
      Navigator.pushReplacement(
          context,
          MaterialPageRoute(
              builder: (context) =>
                  MeetDetailsPage(mdpa: MeetDetailsPageArguments(id))));
    });
  }

  declineRequest(id) async {
    setState(() {
      isLoading = true;
    });
    final url = 'https://.net/Meets/MeetResponse/$id';
    var userToken = await getToken();
    print("Token printed " + userToken.toString());
    var body = jsonEncode({'userToken': '$userToken'});
    /*final responseBody = (await http.get(
            'https://.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
        .body;*/
    /*return */
    http.post(
      url,
      headers: {
        "Content-Type": "application/json",
        "Authorization": "Bearer $userToken"
      },
      /*body: body*/
    ).then((http.Response response) {
      print("Decline Response Status: ${response.statusCode}");
      print("Decline Response Body: ${response.body}");
      setState(() {
        isLoading = false;
      });
      var responseBody = response.body;
    });
  }

  getMeet(id) async {
    setState(() {
      isLoading = true;
    });
    final url = 'https://``````````````.net/Meets/Get/$id';
    var userToken = await getToken();
    print("Token printed " + userToken.toString());
    var body = jsonEncode({'userToken': '$userToken'});
    /*final responseBody = (await http.get(
            'https://``````````.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
        .body;*/
    /*return */
    http.get(
      url,
      headers: {"Authorization": "Bearer $userToken"},
      /*body: body*/
    ).then((http.Response response) async {
      print("Get Response Status: ${response.statusCode}");
      print("Get Response Body: ${response.body}");
      setState(() {
        isLoading = false;
      });
      var responseBody = response.body;
      meets = MeetModel.fromJsonList(json.decode(responseBody));
    });
  }
}

Future<String> getToken() async {
  final storage = new FlutterSecureStorage();
  return await storage.read(key: 'token');
}

class ResponsePageArguments {
  String id;

  ResponsePageArguments(this.id);
}

// Code below is useless
class MeetModel {
  String meetId;
  String host;
  String hostId;
  String address;
  String city;
  String zip;
  String category;
  String latitude;
  String longitude;
  String product;
  String productId;
  String reference;
  String hostPlaceId;
  String venueAddress;
  String venuePlaceId;
  String venueLatitude;
  String venueLongitude;
  String recipient;
  String recipientAddress;
  String recipientZip;
  String recipientCity;
  String recipientPlaceID;
  String recipientLatitude;
  String recipientLongitude;
  String requestTime;
  String responseTime;
  String recipientId;
  String isArchived;
  String meetType;

  MeetModel.fromJson(obj) {
    this.meetId = obj['MeetId'].toString();
    this.host = obj['Host'].toString();
    this.address = obj['Address'].toString();
    this.city = obj['City'].toString();
    this.zip = obj['Zip'].toString();
    this.category = obj['Category'].toString();
    this.latitude = obj['Latitude'].toString();
    this.longitude = obj['Longitude'].toString();
    this.product = obj['Product'].toString();
    this.productId = obj['ProductId'].toString();
    this.reference = obj['Reference'].toString();
    this.hostPlaceId = obj['HostPlaceId'].toString();
    this.venueAddress = obj['VenueAddress'].toString();
    this.venuePlaceId = obj['VenuePlaceId'].toString();
    this.venueLatitude = obj['VenueLatitude'].toString();
    this.venueLongitude = obj['VengueLongitude'].toString();
    this.recipient = obj['Recipient'].toString();
    this.recipientAddress = obj['RecipientAddress'].toString();
    this.recipientZip = obj['RecipientZip'].toString();
    this.recipientPlaceID = obj['RecipientPlaceID'].toString();
    this.recipientLatitude = obj['RecipientLatitude'].toString();
    this.recipientLongitude = obj['RecipientLongitude'].toString();
    this.requestTime = obj['RequestTime'].toString();
    this.responseTime = obj['ResponseTime'].toString();
    this.hostId = obj['HostId'].toString();
    this.recipientId = obj['RecipientId'].toString();
    this.isArchived = obj['IsArchived'].toString();
    this.meetType = obj['MeetType'].toString();
  }

  static List<MeetModel> fromJsonList(jsonList) {
    return jsonList.map<MeetModel>((obj) => MeetModel.fromJson(obj)).toList();
  }
}


会议页面:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:marketapp/Areas/Meet/ResponsePage.dart';

import 'MeetDetailsPage.dart';

class MeetsPage extends StatefulWidget {
  @override
  State createState() => new MeetsPageState();
}

class MeetsPageState extends State<MeetsPage> {
  var meets = new List<MeetModel>();
  var isLoading = false;

  _fetchData() async {
    setState(() {
      isLoading = true;
    });
    final url = 'https://.azurewebsites.net/Meets/GetAll';
    var userToken = await getToken();
    print("Token printed " + userToken.toString());
    var body = jsonEncode({'userToken': '$userToken'});
    /*final responseBody = (await http.get(
            'https://.azurewebsites.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
        .body;*/
    /*return */
    http.post(
      url,
      headers: {
        "Content-Type": "application/json",
        "Authorization": "Bearer $userToken"
      },
      /*body: body*/
    ).then((http.Response response) {
      print("GetAll Response Status: ${response.statusCode}");
      print("GetAll Response Body: ${response.body}");
      setState(() {
        isLoading = false;
      });
      var responseBody = response.body;
      meets = MeetModel.fromJsonList(json.decode(responseBody));
    });
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        /*appBar: AppBar(
          title: Text("Meet List"),
          backgroundColor: Colors.indigo,
        ),*/
        body: isLoading
            ? Center(
                child: CircularProgressIndicator(),
              )
            : ListView.builder(
                itemCount: meets.length,
                itemBuilder: (context, index) {
                  if (meets[index].host == "xxxxxx@gmail.com") { // Do not hard code email.
                    return ListTile(
                      onTap: () {
                        if (meets[index].venueAddress != "null") {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => MeetDetailsPage(
                                      mdpa: MeetDetailsPageArguments(
                                          meets[index].meetId))));
                        } else if (meets[index].venueAddress == "null") {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => ResponsePage(
                                      rpa: ResponsePageArguments(
                                          meets[index].meetId))));
                        }
                      },
                      title: Text(
                          meets[index].recipient,
                          style: TextStyle(fontWeight: FontWeight.w500)),
                      trailing: Icon(
                        Icons.map,
                        color: Colors.blue[500],
                      ),
                      subtitle: Text(meets[index].requestTime),
                    );
                  } else {
                    return ListTile(
                      onTap: () {
                        if (meets[index].venueAddress != "null") {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => MeetDetailsPage(
                                      mdpa: MeetDetailsPageArguments(
                                          meets[index].meetId))));
                        } else if (meets[index].venueAddress == "null") {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => ResponsePage(
                                      rpa: ResponsePageArguments(
                                          meets[index].meetId))));
                        }
                      },
                      title: Text(
                          meets[index].host,
                          style: TextStyle(fontWeight: FontWeight.w500)),
                      trailing: Icon(
                        Icons.map,
                        color: Colors.blue[500],
                      ),
                      subtitle: Text(meets[index].requestTime),
                    );
                  }
                },
              ));
  }

  @override
  void initState() {
    _fetchData();
    super.initState();
  }
}

class MeetModel {
  String meetId;
  String host;
  String hostId;
  String address;
  String city;
  String zip;
  String category;
  String latitude;
  String longitude;
  String product;
  String productId;
  String reference;
  String hostPlaceId;
  String venueAddress;
  String venuePlaceId;
  String venueLatitude;
  String venueLongitude;
  String recipient;
  String recipientAddress;
  String recipientZip;
  String recipientCity;
  String recipientPlaceID;
  String recipientLatitude;
  String recipientLongitude;
  String requestTime;
  String responseTime;
  String recipientId;
  String isArchived;
  String meetType;

  MeetModel.fromJson(obj) {
    this.meetId = obj['MeetId'].toString();
    this.host = obj['Host'].toString();
    this.address = obj['Address'].toString();
    this.city = obj['City'].toString();
    this.zip = obj['Zip'].toString();
    this.category = obj['Category'].toString();
    this.latitude = obj['Latitude'].toString();
    this.longitude = obj['Longitude'].toString();
    this.product = obj['Product'].toString();
    this.productId = obj['ProductId'].toString();
    this.reference = obj['Reference'].toString();
    this.hostPlaceId = obj['HostPlaceId'].toString();
    this.venueAddress = obj['VenueAddress'].toString();
    this.venuePlaceId = obj['VenuePlaceId'].toString();
    this.venueLatitude = obj['VenueLatitude'].toString();
    this.venueLongitude = obj['VengueLongitude'].toString();
    this.recipient = obj['Recipient'].toString();
    this.recipientAddress = obj['RecipientAddress'].toString();
    this.recipientZip = obj['RecipientZip'].toString();
    this.recipientPlaceID = obj['RecipientPlaceID'].toString();
    this.recipientLatitude = obj['RecipientLatitude'].toString();
    this.recipientLongitude = obj['RecipientLongitude'].toString();
    this.requestTime = obj['RequestTime'].toString();
    this.responseTime = obj['ResponseTime'].toString();
    this.hostId = obj['HostId'].toString();
    this.recipientId = obj['RecipientId'].toString();
    this.isArchived = obj['IsArchived'].toString();
    this.meetType = obj['MeetType'].toString();
  }

  static List<MeetModel> fromJsonList(jsonList) {
    return jsonList.map<MeetModel>((obj) => MeetModel.fromJson(obj)).toList();
  }
}

Future<String> getToken() async {
  final storage = new FlutterSecureStorage();
  return await storage.read(key: 'token');
}

class Backend {
  static Future<List<MeetModel>> GetAll(userToken) async {
    final url = 'https://.net/Auths/RegisterDevice';
    var body = jsonEncode({'userToken': '$userToken'});
    /*final responseBody = (await http.get(
            'https://.azurewebsites.net/Auths/RegisterDevice?deviceToken=$deviceToken&userToken=$userToken'))
        .body;*/
    return http
        .post(url,
            headers: {
              "Content-Type": "application/json",
              "Authorization": "Bearer $userToken"
            },
            body: body)
        .then((http.Response response) {
      print("GetAll Response Status: ${response.statusCode}");
      print("GetAll Response Body: ${response.body}");
      var responseBody = response.body;
      return MeetModel.fromJsonList(json.decode(responseBody));
    });
  }
}

该错误仍然会出现,但是在异步调用结束时消失了。注意-当您从Meets列表中选择一个项目时,会发生此错误-它会导航到ResponsePage,并且在短暂的一秒钟内,会出现红色闪烁,表明列表中没有足够的项目。当呼叫以正确的形式结束时,此错误消失。

在满足列表中的数据完成填充之前,是否有办法停止构建卡?

enter image description here enter image description here enter image description here

0 个答案:

没有答案