Flutter之对接接口并显示

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('');
    }
  );
}

即可。

posted @ 2021-06-11 14:28  罗毅豪  阅读(305)  评论(0编辑  收藏  举报