如何修复调用 API 时卡住的颤振应用程序(仅限发布版本)
Posted
技术标签:
【中文标题】如何修复调用 API 时卡住的颤振应用程序(仅限发布版本)【英文标题】:How to fix flutter app stuck in loading when calling API (only Release Version) 【发布时间】:2020-09-07 04:00:21 【问题描述】:我正在为 Covid-19 构建应用程序。 在构建应用程序时,我通过函数调用 API,并且希望仅在成功命中 API 后加载内容。
在调试模式下,一切正常,从 api 获取数据后加载内容,直到显示加载屏幕,但处于发布模式,但卡在加载屏幕。这是示例代码
import 'package:covid_19/widgets/counter.dart';
import 'package:covid_19/widgets/my_header.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:covid_19/API/api.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'constant.dart';
class HomeScreen extends StatefulWidget
@override
_HomeScreenState createState() => _HomeScreenState();
class _HomeScreenState extends State<HomeScreen>
final controller = ScrollController();
double offset = 0;
String countryname="All";
bool loaded=false;
List country=[];
String totalcase="0";
String infectedcase="0";
String deathcase="0";
String recoveredcase="0";
String newcase="0";
String activecase="0";
String criticalcase="0";
String newdeathcase="0";
String testtotal="0";
String day="";
String time="";
List stat=[];
Future getcountry() async
final data=await getcountries.getdata();
setState(()
country=data;
);
getstatss();
Future getstatss() async
final data=await getstats.getdata();
setState(()
stat=data;
);
for(int i=0;i<stat.length;i++)
if(countryname==stat[i]['country'])
setState(()
totalcase=stat[i]['cases']['total'].toString();
recoveredcase=stat[i]['cases']['recovered'].toString();
newcase=stat[i]['cases']['new'].toString();
activecase=stat[i]['cases']['active'].toString();
criticalcase=stat[i]['cases']['critical'].toString();
newdeathcase=stat[i]['deaths']['new'].toString();
deathcase=stat[i]['deaths']['total'].toString();
testtotal=stat[i]['tests']['total'].toString();
day=stat[i]['day'].toString();
time=stat[i]['time'].toString();
);
break;
setState(()
loaded=true;
);
Future filterdata() async
totalcase="0";
infectedcase="0";
deathcase="0";
recoveredcase="0";
newcase="0";
activecase="0";
criticalcase="0";
newdeathcase="0";
testtotal="0";
day="";
time="";
setState(()
loaded=false;
);
for(int i=0;i<stat.length;i++)
print(stat[i]);
if(countryname==stat[i]['country'])
print(countryname);
totalcase=stat[i]['cases']['total'].toString();
recoveredcase=stat[i]['cases']['recovered'].toString();
newcase=stat[i]['cases']['new'].toString();
activecase=stat[i]['cases']['active'].toString();
criticalcase=stat[i]['cases']['critical'].toString();
newdeathcase=stat[i]['deaths']['new'].toString();
deathcase=stat[i]['deaths']['total'].toString();
testtotal=stat[i]['tests']['total'].toString();
day=stat[i]['day'].toString();
time=stat[i]['time'].toString();
setState(()
loaded=true;
);
@override
void initState()
// TODO: implement initState
super.initState();
getcountry();
@override
Widget build(BuildContext context)
return WillPopScope(
onWillPop: () async => false,
child: MaterialApp(
title: "Covid 19",
theme: new ThemeData(
primaryColor: Colors.blue,
primaryColorLight: Color.fromRGBO(111, 196, 242, 1),
),
darkTheme: ThemeData(
brightness: Brightness.dark,
),
home: Scaffold(
body: SingleChildScrollView(
controller: controller,
child:Column(
children: <Widget>[
MyHeader(
image: "assets/icons/Drcorona.svg",
textTop: "You just Need",
textBottom: "to stay at home.",
offset: offset,
),
loaded?Container(
margin: EdgeInsets.symmetric(horizontal: 20),
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
height: 60,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25),
border: Border.all(
color: Color(0xFFE5E5E5),
),
),
child: Row(
children: <Widget>[
SvgPicture.asset("assets/icons/maps-and-flags.svg"),
SizedBox(width: 20),
Expanded(
child: DropdownButton(
isExpanded: true,
underline: SizedBox(),
icon: SvgPicture.asset("assets/icons/dropdown.svg"),
value: countryname,
items: country.map<DropdownMenuItem<dynamic>>((dynamic value)
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
).toList(),
onChanged: (value)
setState(()
countryname=value;
);
filterdata();
,
),
),
],
),
):SizedBox(),
SizedBox(height: 20),
loaded?Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
RichText(
text: TextSpan(
children: [
TextSpan(
text: "Case Update\n",
style: kTitleTextstyle,
),
TextSpan(
text: time!=null||time==""?"Newest update $time.split("T")[0] $time.split("T")[1].split("+")[0]":"Todays Update",
style: TextStyle(
color: kTextLightColor,
),
),
],
),
),
Spacer(),
Text(
"See details",
style: TextStyle(
color: kPrimaryColor,
fontWeight: FontWeight.w600,
),
),
],
),
SizedBox(height: 20),
Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(0, 4),
blurRadius: 30,
color: kShadowColor,
),
],
),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Counter(
color: kInfectedColor,
sizeup:1.5,
number: totalcase=="null"?int.parse("0"):int.parse(totalcase),
title: "Total Cases",
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Counter(
color: kInfectedColor,
number: activecase=="null"?int.parse("0"):int.parse(activecase),
sizeup: 1.2,
title: "Infected",
),
Counter(
color: kDeathColor,
number: deathcase=="null"?int.parse("0"):int.parse(deathcase),
sizeup: 1.2,
title: "Deaths",
),
Counter(
color: kRecovercolor,
number: recoveredcase=="null"?int.parse("0"):int.parse(recoveredcase),
sizeup: 1.2,
title: "Recovered",
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Counter(
color: kInfectedColor,
number: newcase=="null"?int.parse("0"):int.parse(newcase),
sizeup: 1,
title: "New Case",
),
Counter(
color: kDeathColor,
number: newdeathcase=="null"?int.parse("0"):int.parse(newdeathcase),
sizeup: 1,
title: "New Death",
),
Counter(
color: kRecovercolor,
number: testtotal=="null"?int.parse("0"):int.parse(testtotal),
sizeup: 1,
title: "Total Tests",
),
],
),
],
),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Spread of Virus",
style: kTitleTextstyle,
),
Text(
"See details",
style: TextStyle(
color: kPrimaryColor,
fontWeight: FontWeight.w600,
),
),
],
),
Container(
margin: EdgeInsets.only(top: 20),
padding: EdgeInsets.all(20),
height: 178,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
boxShadow: [
BoxShadow(
offset: Offset(0, 10),
blurRadius: 30,
color: kShadowColor,
),
],
),
child: Image.asset(
"assets/images/map.png",
fit: BoxFit.contain,
),
),
],
),
):Center(child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Text("Connecting",style: TextStyle(fontSize: 20),),
SizedBox(height: 50,),
],
),),
],
)),
),
),
);
【问题讨论】:
您不应该在setState
方法上使用任何 逻辑。顾名思义,它应该只为一个新状态改变状态,而不是解析那个或任何东西。尝试将您的 for 循环移到 setState
之外,并且只在其上设置 loaded = true
。
试过了,还是有同样的问题,我会更新问题中的编辑代码。
您将loaded = true
设置在多个位置。我会将您的解析逻辑提取到数据模型中,因为它会使整个小部件变得臃肿和混乱。
这是造成问题的原因吗?我是新手,如果是,我该如何解决?
【参考方案1】:
我很确定问题出在这段代码中。 添加一些 != null 检查或在 min try-catch 时添加一些可能是个好主意 :)
if(countryname==stat[i]['country'])
print(countryname);
totalcase=stat[i]['cases']['total'].toString();
recoveredcase=stat[i]['cases']['recovered'].toString();
newcase=stat[i]['cases']['new'].toString();
activecase=stat[i]['cases']['active'].toString();
criticalcase=stat[i]['cases']['critical'].toString();
newdeathcase=stat[i]['deaths']['new'].toString();
deathcase=stat[i]['deaths']['total'].toString();
testtotal=stat[i]['tests']['total'].toString();
day=stat[i]['day'].toString();
time=stat[i]['time'].toString();
【讨论】:
以上是关于如何修复调用 API 时卡住的颤振应用程序(仅限发布版本)的主要内容,如果未能解决你的问题,请参考以下文章