美文网首页Flutter 入坑记Flutter
flutter 第五天(温故页面布局 然后实现网络请求)

flutter 第五天(温故页面布局 然后实现网络请求)

作者: 雪纳瑞的哈士奇 | 来源:发表于2019-06-03 10:19 被阅读3次

    今天继续写页面 温故下之前的 并且看看有没有 知新0.0

    在不使用默认的tabbar的情况下 做出来可以左右滑动的二级列表(类似tabbar的)

    开始~~~~~

    老铁们 温故温故 就是温柔的用故(guo)去的知识 哈哈哈哈 (小朋友们不要相信 刚刚那句话是给搬砖的人看的 你们都是祖国未来的花朵 要记住 温故而知新的意思是:温习已学的知识,并且由其中获得新的领悟 爱学习的小朋友可以点击这里查看更多)
    是的 我们不使用默认的tabbar 怎样做出来可以类似tabbar的左右滑动的二级列表呢
    其实很多小朋友已经想到了 列表列表 就是要用列表啊
    所以 我们不使用默认的tabbar 怎样做出来可以类似tabbar的左右滑动的二级列表呢
    就是用 横向的ListView 哈哈哈哈哈哈 惊不惊喜 意不意外

    开始温故~~~~~

    其实关键代码就是这一行

    scrollDirection:Axis.horizontal
    

    但是要做出来选中效果的哦

    在布局的时候出现了这个错误


    image.png

    解决中
    解决完毕 解决方法就不说了 太尴尬这个 一点点的问题 太马虎了 这里记个教训 希望老铁们不要马虎 实在想知道 评论区见0.0

    new Container(
                padding: const EdgeInsets.only(top: 8,left: 5,right: 5,bottom: 8),
                height: ScreenUtil().setHeight(46),
                child:  new ListView.builder(
                    scrollDirection: Axis.horizontal,
                    itemCount: secondList.length,
                    itemBuilder: (BuildContext context,int index){
                      return text(index);
                    }
                )
            ),
    
     Widget text(int index){
        return new Container(
          padding: const EdgeInsets.only(left: 10,top: 6,bottom: 6,right: 10),
          margin: const EdgeInsets.only(left: 10),
          height: ScreenUtil().setHeight(26),
          decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(3.0),
              color: Colors.red
          ),
          child: new Text(secondList[index],style: new TextStyle(
              fontSize: 13,
              color: Colors.white
          ),
            textAlign: TextAlign.center,),
        );
      }
    

    这样就完成了可以横向滑动的ListView
    下面写选中状态

    选中状态的话 把第一段代码换成

     int currentNum = 0;
      Widget text(int index){
        Color backColor = Color.fromRGBO(248, 248, 248, 1);
        Color textColor = Colors.black;
        if(currentNum == index){
          backColor = Color.fromRGBO(227, 36, 32, 1);
          textColor = Colors.white;
        }
        return new GestureDetector(
          child: new Container(
            padding: const EdgeInsets.only(left: 10,top: 6,bottom: 6,right: 10),
            margin: const EdgeInsets.only(left: 10),
            height: ScreenUtil().setHeight(26),
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(3.0),
                color: backColor
            ),
            child: new Text(secondList[index],style: new TextStyle(
                fontSize: 13,
                color: textColor
            ),
              textAlign: TextAlign.center,),
          ),
          onTap: (){
            currentNum = index;
            setState(() {
    
            });
          },
        );
      }
    

    也就是把row的代码加上状态和点击事件就行了

    页面传值一:

    子页面:

    class NewList extends StatefulWidget {
      const NewList(Key key, {
        this.titles
      }) : super(key: key);
      final List<String> titles;
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return new Page();
      }
    }
    
    
    class Page extends State<NewList> {
    @override
      Widget build(BuildContext context) {
        ScreenUtil.instance = ScreenUtil(width: value.desginWidth, height: value.desginHeight)..init(context);
        print(widget.titles);
        return layout(context);
      }
    }
    

    父页面:

    NewList(new Key(""),titles: ["通知","公告"],),//通知公告
    

    网络请求

    网络请求 可以使用三方库也可以使用flutter自己官方的类库

    官方的网络请求
    var httpClient = new HttpClient();
      var url = Constant.baseUrl + Controller + Action;
    
      _loadData() async {
        try {
          var request = await httpClient.getUrl(Uri.parse(url));
          var response = await request.close();
          if (response.statusCode == HttpStatus.OK) {
            _result = await response.transform(UTF8.decoder).join();
            //这里解析数据
          } else {
            _result = 'error code : ${response.statusCode}';
          }
        } catch (exception) {
          _result = '网络异常';
        }
    
        // If the widget was removed from the tree while the message was in flight,
        // we want to discard the reply rather than calling setState to update our
        // non-existent appearance.
        if (!mounted) return;
    
        setState(() {});
      }
    

    本文主要记录第三方库dio的使用方法

    Flutter中文网推荐的第三方库dio

    image.png

    dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等...

    必须要先添加依赖

    在pubspec.yaml文件里面添加
    dependencies:
      dio: ^x.x.x  // 请使用pub上的最新版本  https://pub.dev/packages/dio
    

    一个非常简单的例子

    Dio dio = new Dio();
    Response response=await dio.get("https://www.google.com/");
    print(response.data);
    

    当然了 你必须要引入包

    在对应的文件里面引入
    import 'package:dio/dio.dart';
    

    请耐心看完 或者直接往下翻 到 <我的实例>

    发起一个 GET 请求 :

    Response response;
    response=await dio.get("/test?id=12&name=wendu")
    print(response.data.toString());
    // 请求参数也可以通过对象传递,上面的代码等同于:
    response=await dio.get("/test",data:{"id":12,"name":"wendu"})
    print(response.data.toString());
    

    发起一个 POST 请求:

    response=await dio.post("/test",data:{"id":12,"name":"wendu"})
    

    发起多个并发请求:

    response= await Future.wait([dio.post("/info"),dio.get("/token")]);
    

    下载文件:

    response=await dio.download("https://www.google.com/","./xx.html")
    

    发送 FormData:

    FormData formData = new FormData.from({
       "name": "wendux",
       "age": 25,
    });
    response = await dio.post("/info", data: formData)
    

    通过FormData上传多个文件:

    FormData formData = new FormData.from({
       "name": "wendux",
       "age": 25,
       "file1": new UploadFileInfo(new File("./upload.txt"), "upload1.txt"),
       "file2": new UploadFileInfo(new File("./upload.txt"), "upload2.txt"),
         // 支持文件数组上传
       "files": [
          new UploadFileInfo(new File("./example/upload.txt"), "upload.txt"),
          new UploadFileInfo(new File("./example/upload.txt"), "upload.txt")
        ]
    });
    response = await dio.post("/info", data: formData)
    

    创建一个Dio实例,并配置它
    你可以使用默认配置或传递一个可选 Options参数来创建一个Dio实例 :

    Dio dio = new Dio; // 使用默认配置
    
    // 配置dio实例
    dio.options.baseUrl="https://www.xx.com/api"
    dio.options.connectTimeout = 5000; //5s
    dio.options.receiveTimeout=3000;
    
    // 或者通过传递一个 `options`来创建dio实例
    Options options= new Options(
        baseUrl:"https://www.xx.com/api",
        connectTimeout:5000,
        receiveTimeout:3000
    );
    Dio dio = new Dio(options);
    

    请求配置项 默认是get请求

    {
      /// Http method.
      String method;
    
      /// 请求基地址,可以包含子路径,如: "https://www.google.com/api/".
      String baseUrl;
    
      /// Http请求头.
      Map<String, dynamic> headers;
    
      /// 连接服务器超时时间,单位是毫秒.
      int connectTimeout;
    
      ///  响应流上前后两次接受到数据的间隔,单位为毫秒。如果两次间隔超过[receiveTimeout],
      ///  [Dio] 将会抛出一个[DioErrorType.RECEIVE_TIMEOUT]的异常.
      ///  注意: 这并不是接收数据的总时限.
      int receiveTimeout;
    
      /// 请求数据,可以是任意类型.
      var data;
    
      /// 请求路径,如果 `path` 以 "http(s)"开始, 则 `baseURL` 会被忽略; 否则,
      /// 将会和baseUrl拼接出完整的的url.
      String path="";
    
      /// 请求的Content-Type,默认值是[ContentType.JSON].
      /// 如果您想以"application/x-www-form-urlencoded"格式编码请求数据,
      /// 可以设置此选项为 `ContentType.parse("application/x-www-form-urlencoded")`,  这样[Dio]
      /// 就会自动编码请求体.
      ContentType contentType;
    
      /// [responseType] 表示期望以那种格式(方式)接受响应数据。
      /// 目前 [ResponseType] 接受三种类型 `JSON`, `STREAM`, `PLAIN`.
      ///
      /// 默认值是 `JSON`, 当响应头中content-type为"application/json"时,dio 会自动将响应内容转化为json对象。
      /// 如果想以二进制方式接受响应数据,如下载一个二进制文件,那么可以使用 `STREAM`.
      ///
      /// 如果想以文本(字符串)格式接收响应数据,请使用 `PLAIN`.
      ResponseType responseType;
    
      /// `validateStatus` 决定http响应状态码是否被dio视为请求成功, 返回`validateStatus`
      ///  返回`true` , 请求结果就会按成功处理,否则会按失败处理.
      ValidateStatus validateStatus;
    
      /// 用户自定义字段,可以在 [Interceptor]、[Transformer] 和 [Response] 中取到.
      Map<String, dynamic> extra;
    }
    

    响应数据
    当请求成功时会返回一个Response对象,它包含如下字段:

    {
      /// 响应数据,可能已经被转换了类型, 详情请参考Options中的[ResponseType].
      var data;
      /// 响应头
      HttpHeaders headers;
      /// 本次请求信息
      Options request;
      /// Http status code.
      int statusCode;
      /// 响应对象的自定义字段(可以在拦截器中设置它),调用方可以在`then`中获取.
      Map<String, dynamic> extra;
    }
    

    示例如下:

    Response response=await dio.get("https://www.google.com");
    print(response.data);
    print(response.headers);
    print(response.request);
    print(statusCode);
    

    拦截器
    每一个 Dio 实例都有一个请求拦截器 RequestInterceptor 和一个响应拦截器 ResponseInterceptor, 通过拦截器你可以在请求之前或响应之后(但还没有被 then 或 catchError处理)做一些统一的预处理操作。

     dio.interceptor.request.onSend = (Options options){
         // 在请求被发送之前做一些事情
         return options; //continue
         // 如果你想完成请求并返回一些自定义数据,可以返回一个`Response`对象或返回`dio.resolve(data)`。
         // 这样请求将会被终止,上层then会被调用,then中返回的数据将是你的自定义数据data.
         //
         // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象,或返回`dio.reject(errMsg)`,
         // 这样请求将被中止并触发异常,上层catchError会被调用。
     }
     dio.interceptor.response.onSuccess = (Response response) {
         // 在返回响应数据之前做一些预处理
         return response; // continue
     };
     dio.interceptor.response.onError = (DioError e){
         // 当请求失败时做一些预处理
         return e;//continue
     }
    

    如果你想移除拦截器,你可以将它们置为null:

    dio.interceptor.request.onSend=null;
    dio.interceptor.response.onSuccess=null;
    dio.interceptor.response.onError=null;
    

    上面的来自lazyou想了解更多可以去看看

    我的实例

    我使用的是聚合数据的接口

    FormData formData = new FormData.from({
          "type": "top",
          "key": "这个是我在聚合数据上申请的key",
        });
        String url = "http://v.juhe.cn/toutiao/index";
        Dio dio = new Dio();
        Response response = await  dio.post(url,data:formData);
        print(response.toString());
    

    返回的json

    {reason: 成功的返回, result: {stat: 1, data: [{uniquekey: 166143cb8d958c3a0611f7119e011d4c, title: 上海国际水展“2019年好喝中国净水行业创新峰会”正式开幕, date: 2019-06-03 16:26, category: 头条, author_name: 中国新闻网, url: http://mini.eastday.com/mobile/190603162637961.html, thumbnail_pic_s: http://09imgmini.eastday.com/mobile/20190603/20190603162637_ccf1324729c750cb8ca4ae9627f02b4d_6_mwpm_03200403.jpg, thumbnail_pic_s02: http://09imgmini.eastday.com/mobile/20190603/20190603162637_ccf1324729c750cb8ca4ae9627f02b4d_3_mwpm_03200403.jpg, thumbnail_pic_s03: http://09imgmini.eastday.com/mobile/20190603/20190603162637_ccf1324729c750cb8ca4ae9627f02b4d_4_mwpm_03200403.jpg}, {uniquekey: 2af0e385dff1d98150b8586c5a5b5f8c, title: 中国海军第31批护航编队访问澳大利亚, date: 2019-06-03 16:22, category: 头条, author_name: 央视网, url: http://mini.eastday.com/mobile/190603162219489.html, thumbnail_pic_s: http://00imgmini.eastday.com/mobile/20190603/20190603162219_71be
    
    

    现在还只是字符串 由于字符太多 不能完全显示(有那个小伙伴知道flutter的debug跟Android的debug一样可以在断点处显示值并且可以复制请告诉我)

    这个是封装了下网络请求之后的方式

     FormData formData = new FormData.from({
          "type": "top",
          "key": "这个是我在聚合数据上申请的key",
        });
        String url = "http://v.juhe.cn/toutiao/index";
        Map response = await HttpHelper.getInstance().post(url,data: formData);
        print(response);
    

    现在开始解析

    JSON解析
    使用 dart:convert手动序列化JSON
    Flutter中基本的JSON序列化非常简单。Flutter有一个内置dart:convert库,其中包含一个简单的JSON编码器和解码器。
    这个是在聚合上复制下来的格式 先按照这个格式创建I个model

    {
        "reason":"成功的返回",
        "result":{
            "stat":"1",
            "data":[
                {
                    "uniquekey":"6c4caa0c3ba6e05e2a272892af43c00e",
                    "title":"杨幂的发际线再也回不去了么?网友吐槽像半秃",
                    "date":"2017-01-05 11:03",
                    "category":"yule",
                    "author_name":"腾讯娱乐",
                    "url":"[http://mini.eastday.com/mobile/170105110355287.html?qid=juheshuju](http://mini.eastday.com/mobile/170105110355287.html?qid=juheshuju)",
                    "thumbnail_pic_s":"[http://03.imgmini.eastday.com/mobile/20170105/20170105110355_806f4ed3fe71d04fa452783d6736a02b_1_mwpm_03200403.jpeg](http://03.imgmini.eastday.com/mobile/20170105/20170105110355_806f4ed3fe71d04fa452783d6736a02b_1_mwpm_03200403.jpeg)",
                    "thumbnail_pic_s02":"[http://03.imgmini.eastday.com/mobile/20170105/20170105110355_806f4ed3fe71d04fa452783d6736a02b_2_mwpm_03200403.jpeg](http://03.imgmini.eastday.com/mobile/20170105/20170105110355_806f4ed3fe71d04fa452783d6736a02b_2_mwpm_03200403.jpeg)",
                    "thumbnail_pic_s03":"[http://03.imgmini.eastday.com/mobile/20170105/20170105110355_806f4ed3fe71d04fa452783d6736a02b_3_mwpm_03200403.jpeg](http://03.imgmini.eastday.com/mobile/20170105/20170105110355_806f4ed3fe71d04fa452783d6736a02b_3_mwpm_03200403.jpeg)"
                }
            ]
        }
    }
    
    

    TestModel.dart

    class TestModel{
      String uniquekey;
      String title;
      String date;
      String category;
      String author_name;
      String url;
      String thumbnail_pic_s;
      String thumbnail_pic_s02;
      String thumbnail_pic_s03;
      TestModel(){
        uniquekey = "";
        title = "";
        date = "";
        category = "";
        author_name = "";
        url = "";
        thumbnail_pic_s = "";
        thumbnail_pic_s02 = "";
        thumbnail_pic_s03 = "";
      }
    
      TestModel.fromJson(Map<String,dynamic> json) :
            uniquekey = json["uniquekey"],
            title = json["title"],
            date = json["date"],
            category = json["category"],
            author_name = json["author_name"],
            url = json["url"],
            thumbnail_pic_s = json["thumbnail_pic_s"],
            thumbnail_pic_s02 = json["thumbnail_pic_s02"],
            thumbnail_pic_s03 = json["thumbnail_pic_s03"];
    }
    
      //网络请求测试
      Future testNet() async {
        FormData formData = new FormData.from({
          "type": "top",
          "key": "e94932dd98ca1d577d365c26daafadac",
        });
        String url = "http://v.juhe.cn/toutiao/index";
        Map response = await HttpHelper.getInstance().post(url,data: formData);
        if(response["result"]["data"] is List){
          List maps = response["result"]["data"];
          for(int i = 0; i < maps.length ; i++){
            TestModel model = TestModel.fromJson(maps[i]);
            models.add(model);
          }
          print(models[0].title);
        }
      }
    }
    

    这样是可以的 但是感觉很麻烦
    在网上找了一个json_serializable 库 准备试试

    在按照步奏 运行flutter packages pub run build_runner build的时候出现错误

    image.png
    求大神帮忙看下
    引入的包已经引入了 安装的第三方也安装了
    这个问题先放下 暂时不影响使用 明天继续

    上一篇------------------------------------下一篇

    相关文章

      网友评论

        本文标题:flutter 第五天(温故页面布局 然后实现网络请求)

        本文链接:https://www.haomeiwen.com/subject/qtsqxctx.html