利用Flutter寫一個跨平臺的果核APP(3)——網絡請求

前言

緊接上文界面篇,上文中在構建佈局的時候由於是直接將文字圖片顯示出來的,因此消息類Message,和日知錄類One都是採用的無狀態的StatelessWidget類,此次咱們須要調用接口,而後將返回的數據動態的顯示到那兩個控件上去,StatelessWidget類已經沒法知足需求了,這個時候咱們須要使用Flutter提供的另外一個類StatefulWidget,一旦控件繼承了這個類則說明該空間是一個有狀態的控件,能夠進行動態更新等。html

到目前爲止,咱們只使用了無狀態的widget。無狀態widget從它們的父widget接收參數, 它們被存儲在final型的成員變量中。 當一個widget被要求構建時,它使用這些存儲的值做爲參數來構建widget。 爲了構建更復雜的體驗 - 例如,以更有趣的方式對用戶輸入作出反應 - 應用程序一般會攜帶一些狀態。 Flutter使用StatefulWidget來知足這種需求。StatefulWidget是特殊的widget,它知道如何生成State對象,而後用它來保持狀態。git

解析

那麼該如何建立一個有狀態的widget,同時又如何進行網絡請求並對控件的狀態進行更新呢?咱們一個一個的解決。github

  1. 建立一個有狀態的Message控件
//消息
class Message extends StatefulWidget {
  @override
  MessageState createState() => new MessageState();
}

class MessageState extends State<Message> {

  @override
  Widget build(BuildContext context) {
       //這裏建立頁面
  }
}
複製代碼

build函數的內容其實和以前建立無狀態的Message控件的是同樣的,直接複製來就好json

@override
  Widget build(BuildContext context) {
    return new Padding(
      padding: new EdgeInsets.all(18.0),
      child: new Column(
        children: <Widget>[
          new Container(
            child: new Row(
              children: <Widget>[
                new Icon(
                  Icons.message,
                  color: Colors.black26,
                  size: 17.0,
                ),
                new Container(
                  margin: new EdgeInsets.only(left: 5.0),
                  child: new Text(
                    '消息',
                    style: new TextStyle(color: Color(0xFF888888)),
                  ),
                )
              ],
            ),
          ),
          new Divider(
            color: Color(0xFF888888),
          ),
          new Container(
            margin: new EdgeInsets.all(10.0),
            child: new Text("這裏是消息"),
          ),
          new Divider(
            color: Color(0xFF888888),
          )
        ],
      ),
    );
  }
複製代碼
  1. 進行網絡請求並更新控件 在flutter中進行網絡請求有兩種方式
  • 在Flutter中發起HTTP網絡請求
  • 開源庫——dio 在這裏推薦使用第二種,dio是一個強大的Dart Http請求庫,支持Restful API、FormData、攔截器、請求取消、Cookie管理、文件上傳/下載、超時等。和安卓裏的OkHttp相似。具體用法能夠查看傳送門,文檔寫的很詳細。 回到該應用,在這裏咱們須要建立一個getMessage()方法,並經過get請求相應的接口,而後對返回的res進行解析便可,以下所示:
String message = "這裏是消息模塊";

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

  //獲取消息
  void getMessage() {
    Dio().get(Constant.GET_MSG).then((res) {
      if (res.statusCode == 200) {
        int code = res.data['code'];
        if (code == 200) {
          String info = res.data['info'][0];
          print(info);
          setState(() {
            message = info;
          });
        }
      }
    });
  }
複製代碼

說明一下:bash

  1. 調用setState()是相當重要的,由於它告訴框架控件的狀態已經改變,控件應該從新繪製。在這裏的做用就是將以前設置的message變量變爲從接口中獲取的變量。
  2. json的解析,推薦閱讀《在 Flutter 中解析複雜的 JSON》
  3. 咱們若是須要在控件一開始渲染的時候就要發送網絡請求,須要在initState()函數中調用getMessage()方法

該頁代碼

由於日知錄部分的基本上也是網絡請求和動態渲染控件,道理是一致的,因此我就直接在這裏貼上代碼了。網絡

import 'package:flutter/material.dart';
import 'package:flutter_guohe/common/eventBus.dart';
import 'package:dio/dio.dart';
import 'package:flutter_guohe/views/customview.dart';
import 'package:flutter_guohe/utils/constant.dart';

class Today extends StatefulWidget {
  @override
  TodayState createState() => new TodayState();
}

class TodayState extends State<Today> {
  //打開drawer
  void openDrawer() {
    eventBus.fire(new EventOpenDrawer(true));
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          leading: new IconButton(
            icon: Icon(Icons.home),
            onPressed: () {
              //打開drawer
              openDrawer();
            },
          ),
          title: new Text("今日"), //設置標題內容
          backgroundColor: Color.fromARGB(255, 119, 136, 213), //設置appbar背景顏色
          centerTitle: true, //設置標題是否局中
        ),
        body: new ListView(
          children: <Widget>[
            new Header(), //頭部
            new BigDivider(),
            new TodayKb(), //今日課表
            new BigDivider(),
            new Message(), //消息
            new BigDivider(),
            new One() //日知錄
          ],
        ),
      ),
    );
  }
}

//首頁的頭部信息
class Header extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Container(
      height: 100.0,
      margin: new EdgeInsets.all(8.0),
      child: new Row(
        children: <Widget>[
          new Expanded(
            child: new Column(
              children: <Widget>[
                //頭像
                new Container(
                  width: 60.0,
                  height: 60.0,
                  margin: new EdgeInsets.all(8.0),
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: new AssetImage('assets/imgs/ic_menu_score.png'),
                      //從Assets加載圖片
                      fit: BoxFit.cover,
                    ),
                    shape: BoxShape.circle,
                  ),
                ),
                new Text(
                  '查成績',
                  textAlign: TextAlign.center,
                )
              ],
            ),
            flex: 1,
          ),
          new Expanded(
            child: new Column(
              children: <Widget>[
                //頭像
                new Container(
                  width: 60.0,
                  height: 60.0,
                  margin: new EdgeInsets.all(8.0),
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: new AssetImage('assets/imgs/ic_menu_pe.png'),
                      //從Assets加載圖片
                      fit: BoxFit.cover,
                    ),
                    shape: BoxShape.circle,
                  ),
                ),
                new Text(
                  '查體育',
                  textAlign: TextAlign.center,
                )
              ],
            ),
            flex: 1,
          ),
          new Expanded(
            child: new Column(
              children: <Widget>[
                //頭像
                new Container(
                  width: 60.0,
                  height: 60.0,
                  margin: new EdgeInsets.all(8.0),
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: new AssetImage('assets/imgs/ic_menu_bus.png'),
                      //從Assets加載圖片
                      fit: BoxFit.cover,
                    ),
                    shape: BoxShape.circle,
                  ),
                ),
                new Text(
                  '查校車',
                  textAlign: TextAlign.center,
                )
              ],
            ),
            flex: 1,
          ),
          new Expanded(
            child: new Column(
              children: <Widget>[
                //頭像
                new Container(
                  width: 60.0,
                  height: 60.0,
                  margin: new EdgeInsets.all(8.0),
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: new AssetImage('assets/imgs/ic_menu_system.png'),
                      //從Assets加載圖片
                      fit: BoxFit.cover,
                    ),
                    shape: BoxShape.circle,
                  ),
                ),
                new Text(
                  '校園系統',
                  textAlign: TextAlign.center,
                )
              ],
            ),
            flex: 1,
          ),
          new Expanded(
            child: new Column(
              children: <Widget>[
                //頭像
                new Container(
                  width: 60.0,
                  height: 60.0,
                  margin: new EdgeInsets.all(8.0),
                  decoration: BoxDecoration(
                    image: DecorationImage(
                      image: new AssetImage('assets/imgs/ic_menu_more.png'),
                      //從Assets加載圖片
                      fit: BoxFit.cover,
                    ),
                    shape: BoxShape.circle,
                  ),
                ),
                new Text(
                  '更多',
                  textAlign: TextAlign.center,
                )
              ],
            ),
            flex: 1,
          ),
        ],
      ),
    );
  }
}

//今日課表
class TodayKb extends StatefulWidget {
  @override
  TodayKbState createState() => new TodayKbState();
}

class TodayKbState extends State<TodayKb> {
  @override
  Widget build(BuildContext context) {
    //跳轉至課表
    _toKb() {
      print('跳轉至課表');
    }

    return new Padding(
      padding: new EdgeInsets.all(18.0),
      child: new Column(
        children: <Widget>[
          new Container(
            child: new Row(
              children: <Widget>[
                new Icon(
                  Icons.camera,
                  color: Colors.black26,
                  size: 17.0,
                ),
                new Container(
                  margin: new EdgeInsets.only(left: 5.0),
                  child: new Text(
                    '今日課表',
                    style: new TextStyle(color: Color(0xFF888888)),
                  ),
                )
              ],
            ),
          ),
          new Divider(
            color: Color(0xFF888888),
          ),
          new Container(
            margin: new EdgeInsets.only(top: 30.0, bottom: 2.0),
            child: new Text("今天竟然沒有課~" + "\uD83D\uDE01"),
          ),
          new GestureDetector(
            child: new Container(
              margin: new EdgeInsets.only(top: 30.0, bottom: 2.0),
              child: new Text('點我查看完整課表',
                  style: new TextStyle(
                      color: Color(
                        0xFF888888,
                      ),
                      fontSize: 12.0)),
            ),
            onTap: _toKb,
          ),
        ],
      ),
    );
  }
}

//消息
class Message extends StatefulWidget {
  @override
  MessageState createState() => new MessageState();
}

class MessageState extends State<Message> {
  String message = "這裏是消息模塊";

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

  //獲取消息
  void getMessage() {
    Dio().get(Constant.GET_MSG).then((res) {
      if (res.statusCode == 200) {
        int code = res.data['code'];
        if (code == 200) {
          String info = res.data['info'][0];
          print(info);
          setState(() {
            message = info;
          });
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: new EdgeInsets.all(18.0),
      child: new Column(
        children: <Widget>[
          new Container(
            child: new Row(
              children: <Widget>[
                new Icon(
                  Icons.message,
                  color: Colors.black26,
                  size: 17.0,
                ),
                new Container(
                  margin: new EdgeInsets.only(left: 5.0),
                  child: new Text(
                    '消息',
                    style: new TextStyle(color: Color(0xFF888888)),
                  ),
                )
              ],
            ),
          ),
          new Divider(
            color: Color(0xFF888888),
          ),
          new Container(
            margin: new EdgeInsets.all(10.0),
            child: new Text(message),
          ),
          new Divider(
            color: Color(0xFF888888),
          )
        ],
      ),
    );
  }
}

//日知錄
class One extends StatefulWidget {
  @override
  OneState createState() => new OneState();
}

class OneState extends State<One> {
  String date = "2018/09/14";
  String imgUrl = 'http://image.wufazhuce.com/Fn5E1UnrcvN0jwFRiOtDZ2WnQa4N';
  String imgAuthor = "Fahmi Ramadhan";
  String imgKind = "攝影";
  String url = "http://m.wufazhuce.com/one/2202";
  String word = "戀愛不是用談的,是墜入的。";
  String wordFrom = "《寂寞東京鐵塔》";

  //獲取日知錄的內容
  void getOneContent() {
    FormData formData = new FormData.from(
        {"TransCode": "030111", "OpenId": "123456789", "Body": "123456789"});
    Dio().post(Constant.ONE, data: formData).then((res) {
      setState(() {
        date = res.data['Body']['date']
            .toString()
            .split(" ")[0]
            .replaceAll("-", "/");
        imgUrl = res.data['Body']['img_url'];
        imgAuthor = res.data['Body']['img_author'];
        imgKind = res.data['Body']['img_kind'];
        url = res.data['Body']['url'];
        word = res.data['Body']['word'];
        wordFrom = res.data['Body']['word_from'];
      });
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    getOneContent();
  }

  @override
  Widget build(BuildContext context) {
    return new Padding(
      padding: new EdgeInsets.all(18.0),
      child: new Column(
        children: <Widget>[
          new Container(
            child: new Row(
              children: <Widget>[
                new Icon(
                  Icons.email,
                  color: Colors.black26,
                  size: 17.0,
                ),
                new Container(
                  margin: new EdgeInsets.only(left: 5.0),
                  child: new Text(
                    '日知錄',
                    style: new TextStyle(color: Color(0xFF888888)),
                  ),
                )
              ],
            ),
          ),
          new Divider(
            color: Color(0xFF888888),
          ),
          new Container(
            margin: new EdgeInsets.all(10.0),
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Text(
                  date,
                  style: new TextStyle(color: Color(0xFF888888)),
                ),
                new Margin(indent: 6.0),
                new Image(image: new NetworkImage(imgUrl)),
                new Margin(indent: 6.0),
                new Text(
                  imgAuthor + " | " + imgKind,
                  style: new TextStyle(color: Color(0xFF888888)),
                ),
                new Margin(indent: 6.0),
                new Text(
                  word,
                  textAlign: TextAlign.center,
                  style: new TextStyle(color: Color(0xFF888888)),
                ),
                new Margin(indent: 6.0),
                new Text(
                  wordFrom,
                  style: new TextStyle(color: Color(0xFF888888)),
                )
              ],
            ),
          ),
          new Divider(
            color: Color(0xFF888888),
          )
        ],
      ),
    );
  }
}
複製代碼
相關文章
相關標籤/搜索