Fluter对接接口并显示的整个过程还是比较复杂的,我花了比较长的时间进行研究,以对接查询接口为例,整理如下:
若接口的返回数据为:
[{"id":1,"question":"世界上最大的海洋是?","type":"radio","options":"北冰洋,太平洋,印度洋","rightAnswer":"太平洋"},{"id":2,"question":"下面这张图是谁?","type":"radio","options":"陈独秀,李大钊,叶挺,胡适,蔡锷,胡宗南","rightAnswer":"李大钊","pic":"https://z3.ax1x.com/2021/05/22/gOiiKH.jpg"},{"id":3,"question":"要慎重对待朋友交往,坚持择善而交,多同()交朋友,注意净化自己的社交圈。","type":"radio","options":"普通群众,基层干部,先进模范,专家学者","rightAnswer":"普通群众"},{"id":4,"question":"1927年9月29日,秋收起义各部队到达江西永新县三湾村,在毛领导下进行了改编,史称三湾改编。三湾改编的措施( )。","type":"checkbox","checkboxOptions":[{"id":1,"title":"确立了毛在党中央和红军的领导地位","isRight":0,"quizId":4},{"id":2,"title":"开始改变旧军队的习气和不良作风","isRight":1,"quizId":4},{"id":3,"title":"从组织上确立了党对军队的领导","isRight":1,"quizId":4},{"id":4,"title":"是建设无产阶级领导的新型人民军队的重要开端","isRight":1,"quizId":4}]},{"id":5,"question":"通过延安整风,中共初步确立了密切联系群众的思想路线,将马克思主义中国化的第一个理论成果确定为党的指导思想。","type":"radio","options":"对,错","rightAnswer":"错"}]
1.在pubspec.yaml文件中增加dio依赖,然后安装依赖
如:
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.3
fluttertoast: ^3.0.3
shared_preferences: ^0.5.1
dio: 3.0.9
2.新建一个异步函数,用getDioQuiz函数进行网络请求,使用await等待拿到结果,最后函数返回一个List。
Future<List> fetchData() async{
List arr = await getDioQuiz();return arr;
}
getDioQuiz函数代码如下,quizList即为需要显示的列表:
static Future<List> getDioQuiz() async{
Dio dio = new Dio();
Response response = await dio.get(Global.host + "getAllQuiz");
List<Quiz> quizList = (response.data as List<dynamic>).map((e) => Quiz.fromJson((e as Map<String,dynamic>))).toList();
return quizList;
}
其中Global.host是一个静态全局变量
global.dart代码如下:
class Global{
static bool isChangeQuizOrder = true;
static bool isChangeOptionOrder = true;
static String dropdownValue = 'all';
static String host = "http://1.15.186.160:8003/quiz/";
}
3.新建Quiz和Option对应的实体类quiz.dart和option.dart。
quiz.dart
import 'option.dart';
class Quiz {
int id;
String question;
String type;
String options;
String rightAnswer;
String pic;
List<Option> checkboxOptions;
Quiz({this.id, this.question, this.type, this.options, this.rightAnswer, this.pic, this.checkboxOptions});
Quiz.fromJson(Map<String, dynamic> json) {
id = json['id'];
question = json['question'];
type = json['type'];
options = json['options'];
rightAnswer = json['rightAnswer'];
pic = json['pic'];
if (json['checkboxOptions'] != null) {
checkboxOptions = new List<Option>();
json['checkboxOptions'].forEach((v) {
checkboxOptions.add(new Option.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['question'] = this.question;
data['type'] = this.type;
data['options'] = this.options;
data['rightAnswer'] = this.rightAnswer;
data['pic'] = this.pic;
data['checkboxOptions'] = this.checkboxOptions;
if (this.checkboxOptions != null) {
data['checkboxOptions'] = this.checkboxOptions.map((v) => v.toJson()).toList();
}
return data;
}
}
option.dart
class Option {
int id;
String title;
int isRight;
int quizId;
bool isSelected;
Option({this.id, this.title, this.isRight, this.quizId, this.isSelected=false});
factory Option.fromJson(Map<String, dynamic> json) {
return Option(
id: json['id'],
title: json['title'],
isRight: json['isRight'],
quizId: json['quizId'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['title'] = this.title;
data['isRight'] = this.isRight;
data['quizId'] = this.quizId;
return data;
}
}
4.在build函数中加上FutureBuilder组件等待接口请求返回数据
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
appBar: AppBar(
title: Text('问题${_count + 1}'),
),
body: Container(
child: ListView(children: <Widget>[
Column(
children: <Widget>[
Container(
child: Text((list[_count] as Quiz).question,
style: TextStyle(fontSize: 20, color: Colors.black)),
margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 20.0),
),
showPic(),
Column(children: generateOptions()),
],
)
]),
)
);
}
return Text('');
}
);
}
return Text('')为请求接口时显示的页面,可以修改为:
return Scaffold(
body: Center(
child: Text('页面加载中……'),
),
);
5.由于build函数会在程序运行过程中多次执行,导致fetchData函数也被多次执行。
要想让fetchData函数只被执行一次。我们可以在类里新建状态值
Future _fetchData;
在initState进行调用
@override
void initState(){
_fetchData = fetchData();
super.initState();
}
再换掉build里future对应的值
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: _fetchData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Scaffold(
appBar: AppBar(
title: Text('问题${_count + 1}'),
),
body: Container(
child: ListView(children: <Widget>[
Column(
children: <Widget>[
Container(
child: Text((list[_count] as Quiz).question,
style: TextStyle(fontSize: 20, color: Colors.black)),
margin: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 20.0),
),
showPic(),
Column(children: generateOptions()),
],
)
]),
)
);
}
return Text('');
}
);
}
即可。