Flutter網(wǎng)絡(luò)請求,解析json數(shù)據(jù),列表展示

實現(xiàn)效果:


image

需要使用到的第三方網(wǎng)絡(luò)庫:dio

在pubspec.yaml中添加第三方庫(相當于Android Studio中的build gradle目錄)
dio: ^0.0.14 (dio第三方庫名,^后面代表版本號,點擊packages get后完成依賴)

使用干貨提供的JSON數(shù)據(jù)。
http://gank.io/api/data/

json格式如下:
{
"error": false,
"results": [
{
"_id": "5b3d883f421aa906e5b3c6f1",
"createdAt": "2018-07-05T10:53:51.361Z",
"desc": "2018-07-05",
"publishedAt": "2018-07-05T00:00:00.0Z",
"source": "web",
"type": "\u798f\u5229",
"url": "http://ww1.sinaimg.cn/large/0065oQSqly1fsysqszneoj30hi0pvqb7.jpg",
"used": true,
"who": "lijinshanmx"
}
]
}

第一步:

建立JSON所對應(yīng)得model類,解析過程在FLModel.formJson()中處理,對應(yīng)key即可解析,這里注意類型必須對應(yīng),否則解析失敗,比如返回String類型,你聲明時卻是int,這里不會自動轉(zhuǎn)換,導(dǎo)致數(shù)據(jù)無法解析出來。

/解析類

  class FLModle{
     final String _id;
      final String createdAt;
    final String desc;
    final String publishedAt;
    final String source;
    final String type;
    final String url;
    final bool used;
    final String who;

    const FLModle(this._id, this.createdAt, this.desc, this.publishedAt, this.source,
    this.type, this.url, this.used, this.who);

@override
  String toString() {
    return 'FLModle{_id: $_id, createdAt: $createdAt, desc: $desc, publishedAt: $publishedAt, source: $source, type: $type, url:           $url, used: $used, who: $who}';
  }

    FLModle.fromJson(Map<String, dynamic> json)
    : _id = json['_id'],
    createdAt = json['createdAt'],
    desc = json['desc'],
    publishedAt = json['publishedAt'],
    source = json['source'],
    type = json['publishedAt'],
    url = json['url'],
    used = json['used'],
    who = json['who'];
  }

第二步:

創(chuàng)建一個有狀態(tài)的組件,繼承StatefulWidget,在createState方法中創(chuàng)建我們繼承State的組件。

class MeziList extends StatefulWidget{
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return new MeziSateList();
  }
}

第三步:創(chuàng)建MeziSateList,繼承State組件,可通過setState來更新UI,相當于Android中的runOnUI
(此處內(nèi)代碼放在最后一步編寫)。

class MeziSateList extends State<MeziList>{
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        }
      }

第四步:

構(gòu)建網(wǎng)絡(luò)請求,返回需要的List集合,使用async和await來完成耗時的操作,相當關(guān)android中的子線程,F(xiàn)uture類似于消息機制(個人觀點,只是為了簡單理解):

          Future<List<FLModle>>  _getDate(int pageNum,int pageSize) async{
        List flModels;
        String url = Constant.baseUrl + '福利/$pageSize/$pageNum';
        print(url);
          Response response = await dio.get(url);
          if(response.statusCode== HttpStatus.OK){//響應(yīng)成功
              flModels = (response.data)['results'] ;
              currentpage = currentpage+1;//加載成功后才可加載下一頁
          }else{//出問題
         }
        print(flModels.map((model) {
          return new FLModle.fromJson(model);
        }).toList().length);

        return flModels.map((model) {
          return new FLModle.fromJson(model);
      }).toList();

          }


  Future<List<FLModle>> feach(int pageNum,int pageSize){
return _getDate(pageNum, pageSize);
  }

第四步:編寫加載更多和刷新各自對應(yīng)的邏輯

//刷新時調(diào)用

  Future<Null> _refreshData(){

final Completer<Null> completer = new Completer<Null>();
currentpage = 1;
feach(currentpage, pageSize).then((list) {
  setState(() {
      datas = list;
  });
}).catchError((error) {
  print(error);
});
completer.complete(null);
return completer.future;
  }

//加載更多時調(diào)用

  Future<Null> _loadMoreData(){

final Completer<Null> completer = new Completer<Null>();


feach(currentpage, pageSize).then((list) {
  setState(() {
      datas.addAll(list);
  });
}).catchError((error) {
  print(error);
});
completer.complete(null);

return completer.future;
  }

第五步:

創(chuàng)建ScrollController來監(jiān)聽ListView的滑動,需要在initState方法中addListener,并且在dispose中removeListener。

/滑動到底了自動加載更多

  void _scrollListener(){
if(_scrollController.position.pixels==_scrollController.position.maxScrollExtent){
  _loadMoreData();
}
  }

//頁面初始化時加載數(shù)據(jù)并實例化ScrollController

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _refreshData();
    _scrollController = new ScrollController()..addListener(_scrollListener);
  }

   @override
    void dispose() {
      // TODO: implement dispose
    super.dispose();
    _scrollController.removeListener(_scrollListener);
  }

第六步:

創(chuàng)建item并實現(xiàn)點擊事件

Widget buildCardItem(BuildContext context,int index){
    final String url = datas[index].url;
    return new GestureDetector(//點擊事件
      onTap: (){

       _showPhoto(url);
      },
      child: new Card(
        child: new Container(
          padding: EdgeInsets.all(8.0),
          child: new Image.network(url),
        ),
      ),
    );
  }

最后一步:

構(gòu)建ListView,數(shù)據(jù)加載時顯示圓環(huán)

 @override
  Widget build(BuildContext context) {
    // TODO: implement build
    var content ;
    if(datas.isEmpty){
      content =  new Center(child: new CircularProgressIndicator());;
    }else{
      content = new ListView.builder(
        physics: AlwaysScrollableScrollPhysics(),
        itemCount: datas.length,
        controller: _scrollController,
        itemBuilder: buildCardItem,
      );
    }

    var _refreshIndicator = new RefreshIndicator(
        onRefresh: _refreshData,
      child: content,
    );
    return _refreshIndicator;
  }

完整代碼

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'progreess_dialog.dart';
import 'package:easy_app/multi_touch_page.dart';
import 'constant.dart';
//解析類

class FLModle{
  final String _id;
  final String createdAt;
  final String desc;
  final String publishedAt;
  final String source;
  final String type;
  final String url;
  final bool used;
  final String who;

  const FLModle(this._id, this.createdAt, this.desc, this.publishedAt, this.source,
      this.type, this.url, this.used, this.who);

  @override
  String toString() {
    return 'FLModle{_id: $_id, createdAt: $createdAt, desc: $desc, publishedAt: $publishedAt, source: $source, type: $type, url: $url, used: $used, who: $who}';
  }

  FLModle.fromJson(Map<String, dynamic> json)
  : _id = json['_id'],
    createdAt = json['createdAt'],
    desc = json['desc'],
    publishedAt = json['publishedAt'],
    source = json['source'],
    type = json['publishedAt'],
    url = json['url'],
    used = json['used'],
    who = json['who'];
}

class TabGirlPage extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
// TODO: implement build
    return new Scaffold(
     body: new MeziList(),
    );
  }

}

class MeziList extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new MeziSateList();
  }
}

class MeziSateList extends State<MeziList>{

  List<FLModle> datas = [];//初始化列表數(shù)據(jù)源
  int currentpage = 1;//默認當前頁
  int pageSize = 10;//每頁加載數(shù)據(jù)


  Dio dio = new Dio();//第三方網(wǎng)絡(luò)加載庫
  ScrollController _scrollController;

  //滑動到底了自動加載更多
  void _scrollListener(){
    if(_scrollController.position.pixels==_scrollController.position.maxScrollExtent){
      _loadMoreData();
    }
  }

//頁面初始化時加載數(shù)據(jù)并實例化ScrollController
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _refreshData();
    _scrollController = new ScrollController()..addListener(_scrollListener);
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    _scrollController.removeListener(_scrollListener);
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    var content ;
    if(datas.isEmpty){
      content =  new Center(child: new CircularProgressIndicator());;
    }else{
      content = new ListView.builder(
        physics: AlwaysScrollableScrollPhysics(),
        itemCount: datas.length,
        controller: _scrollController,
        itemBuilder: buildCardItem,
      );
   }  

    var _refreshIndicator = new RefreshIndicator(
        onRefresh: _refreshData,
      child: content,
    );
    return _refreshIndicator;
  }

  void _showPhoto(String url) {
    Navigator.of(context).push(new PageRouteBuilder(
        opaque: false,
        pageBuilder: (BuildContext context, _, __) {
          return new MultiTouchPage(url);
        },
        transitionsBuilder: (_, Animation<double> animation, __, Widget child) {
          return new FadeTransition(
            opacity: animation,
            child: new RotationTransition(
              turns: new Tween<double>(begin: 0.5, end: 1.0).animate(animation),
              child: child,
            ),
          );
        }));
  }

  Widget buildCardItem(BuildContext context,int index){
    final String url = datas[index].url;
   return new GestureDetector(//點擊事件
      onTap: (){
     
        _showPhoto(url);
      },
        child: new Card(
        child: new Container(
          padding: EdgeInsets.all(8.0),
          child: new Image.network(url),
        ),
      ),
    );
  }

  //刷新時調(diào)用
      Future<Null> _refreshData(){

    final Completer<Null> completer = new Completer<Null>();
    currentpage = 1;
    feach(currentpage, pageSize).then((list) {
      setState(() {
          datas = list;
      });
    }).catchError((error) {
      print(error);
    });
    completer.complete(null);
    eturn completer.future;
  }

  //加載更多時調(diào)用
  Future<Null> _loadMoreData(){

    final Completer<Null> completer = new Completer<Null>();


    feach(currentpage, pageSize).then((list) {
      setState(() {
          datas.addAll(list);
      });
    }).catchError((error) {
      print(error);
    });
    completer.complete(null);

    return completer.future;
  }

  Future<List<FLModle>> feach(int pageNum,int pageSize){
   return _getDate(pageNum, pageSize);
  }

  Future<List<FLModle>>  _getDate(int pageNum,int pageSize) async{
    List flModels;
    String url = Constant.baseUrl + '福利/$pageSize/$pageNum';
    print(url);
      Response response = await dio.get(url);
      if(response.statusCode== HttpStatus.OK){//響應(yīng)成功
          flModels = (response.data)['results'] ;
          currentpage = currentpage+1;//加載成功后才可加載下一頁
      }else{//出問題
      }
    print(flModels.map((model) {
      return new FLModle.fromJson(model);
    }).toList().length);

    return flModels.map((model) {
      return new FLModle.fromJson(model);
    }).toList();

  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容