Flutter-防京东商城项目-编写详情页面商品通过接口获取数据-21

一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。

代码文档

Flutter防京东商城源码(1-10)链接

Flutter防京东商城源码(11-20)链接

Flutter防京东商城源码(21-30)链接

Flutter防京东商城源码(31-46)链接

效果
请添加图片描述

本章目标:
1.获取网络数据,赋值到第一个视图里面

商品详情获取回来的网络数据

{"result":{"_id":"5a0425bc010e711234661439","title":"磨砂牛皮男休闲鞋-有属性","cid":"5a042480010e711234661436","price":"688","old_price":"368","is_best":1,"is_hot":"1","is_new":"1","attr":[{"cate":"鞋面材料","list":["牛皮 "]},{"cate":"闭合方式","list":["系带"]},{"cate":"颜色","list":["红色","白色","黄色"]}],"status":1,"pic":"public\\upload\\RinsvExKu7Ed-ocs_7W1DxYO.png","content":"<p style=\"margin: 1.12em 0px; padding: 0px; text-align: center; line-height: 1.4; color: rgb(64, 64, 64); font-family: tahoma, arial, 宋体, sans-serif; font-size: 14px;\"><strong>非凡舒适,经久耐穿,融入飞翔元素,让你无论身处何处,都备受瞩目</strong><br /><br /><img alt=\"\" src=\"https://img30.360buyimg.com/popWaterMark/jfs/t7390/58/3849479320/166969/b8c17cad/59fabd2fNcd1ed823.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: middle;\" /></p><p style=\"margin: 1.12em 0px; padding: 0px; text-align: center; line-height: 1.4; color: rgb(64, 64, 64); font-family: tahoma, arial, 宋体, sans-serif; font-size: 14px;\"><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img30.360buyimg.com/imgzone/jfs/t10504/182/2465321261/89642/619c161b/59f831b8Nb84a4b96.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img14.360buyimg.com/imgzone/jfs/t9772/268/2466805940/61723/34d37efb/59f831cdNded68405.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img14.360buyimg.com/imgzone/jfs/t9775/81/2512315198/70050/331ea0d4/59f831cdN3c6df0aa.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img14.360buyimg.com/imgzone/jfs/t11653/222/774240663/68769/d8e9ff98/59f831ceN35a4273f.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img12.360buyimg.com/imgzone/jfs/t10636/218/2491518591/68633/ac6c5b05/59f831caN262904b1.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img14.360buyimg.com/imgzone/jfs/t10732/210/2485945643/66258/7276a664/59f831caNd20e2b4a.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /></p><img class=\"desc_anchor img-ks-lazyload\" id=\"desc-module-2\" alt=\"\" src=\"https://img10.360buyimg.com/imgzone/jfs/t11101/10/781218477/43/9acceab1/59f831aaN8687189b.gif\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; text-align: center; height: 1px; display: block; clear: both; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; color: rgb(64, 64, 64); font-family: tahoma, arial, 宋体, sans-serif; font-size: 14px; line-height: 21px;\" /><p style=\"margin: 1.12em 0px; padding: 0px; text-align: center; line-height: 1.4; color: rgb(64, 64, 64); font-family: tahoma, arial, 宋体, sans-serif; font-size: 14px;\"><br /></p><p style=\"margin: 1.12em 0px; padding: 0px; text-align: center; line-height: 1.4; color: rgb(64, 64, 64); font-family: tahoma, arial, 宋体, sans-serif; font-size: 14px;\"><img class=\"img-ks-lazyload\" alt=\"\" src=\"https://img10.360buyimg.com/imgzone/jfs/t10399/103/2508090813/543802/dcc5fa46/59f831d4N87a2bc5d.jpg\" style=\"margin: 0px; padding: 0px; border: 0px; vertical-align: top; animation: ks-fadeIn 350ms linear 0ms 1 normal both; opacity: 1; float: none;\" align=\"absmiddle\" /></p>","cname":"男鞋","sub_title":"非凡舒适,经久耐穿,融入飞翔元素,让你无论身处何处,都备受瞩目","salecount":275}}

1.编写数据模型

在这里插入图片描述


class ProductContentModel {
  ProductContentitem result;

  ProductContentModel({this.result});

  ProductContentModel.fromJson(Map<String, dynamic> json) {
    result =
    json['result'] != null ? new ProductContentitem.fromJson(json['result']) : null;
  }
  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    if (this.result != null) {
      data['result'] = this.result.toJson();
    }
    return data;
  }
}

class ProductContentitem {

  String sId;
  String title;
  String cid;
  Object price;
  Object oldPrice;
  Object isBest;
  Object isHot;
  Object isNew;
  Object status;
  Object pic;
  String content;
  String cname;
  List<Attr> attr;
  String subTitle;
  Object salecount;

  ProductContentitem(
      {this.sId,
        this.title,
        this.cid,
        this.price,
        this.oldPrice,
        this.isBest,
        this.isHot,
        this.isNew,
        this.status,
        this.pic,
        this.content,
        this.cname,
        this.attr,
        this.subTitle,
        this.salecount});

  ProductContentitem.fromJson(Map<String, dynamic> json) {
    sId = json['_id'];
    title = json['title'];
    cid = json['cid'];
    price = json['price'];
    oldPrice = json['old_price'];
    isBest = json['is_best'];
    isHot = json['is_hot'];
    isNew = json['is_new'];
    status = json['status'];
    pic = json['pic'];
    content = json['content'];
    cname = json['cname'];
    if (json['attr'] != null) {
      attr = new List<Attr>();
      json['attr'].forEach((v) {
        attr.add(new Attr.fromJson(v));
      });
    }
    subTitle = json['sub_title'];
    salecount = json['salecount'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['_id'] = this.sId;
    data['title'] = this.title;
    data['cid'] = this.cid;
    data['price'] = this.price;
    data['old_price'] = this.oldPrice;
    data['is_best'] = this.isBest;
    data['is_hot'] = this.isHot;
    data['is_new'] = this.isNew;
    data['status'] = this.status;
    data['pic'] = this.pic;
    data['content'] = this.content;
    data['cname'] = this.cname;
    if (this.attr != null) {
      data['attr'] = this.attr.map((v) => v.toJson()).toList();
    }
    data['sub_title'] = this.subTitle;
    data['salecount'] = this.salecount;
    return data;
  }
}

class Attr {
  String cate;
  List<String> list;

  Attr({this.cate, this.list});

  Attr.fromJson(Map<String, dynamic> json) {
    cate = json['cate'];
    list = json['list'].cast<String>();
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['cate'] = this.cate;
    data['list'] = this.list;
    return data;
  }
}

2.回到详情商品页 ProductContent

导入头文件

import '../config/Config.dart';
import 'package:dio/dio.dart';
import '../model/ProductContentModel.dart';
import '../widget/LoadingWidget.dart';

写到详情页的主控制器里面

List _productContentList=[];

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

_getContentData() async{
  var api ='${Config.domain}api/pcontent?id=${widget.arguments['id']}';
  print(api);
  var result = await Dio().get(api);
  var productContent = new ProductContentModel.fromJson(result.data);
  setState(() {
    this._productContentList.add(productContent.result);
  });
}

3.修改下面的代码

3.2.判断获取回来有数据才把数据传递进去2.把获取回来的数据传递到商品控件里面

在这里插入图片描述

body: this._productContentList.length>0?Stack(
  children: <Widget>[
    TabBarView(
        children: <Widget>[
          ProductContentFirst(this._productContentList),
          ProductContentSecond(this._productContentList),
          ProductContentThird()
        ],
     ),
     Positioned(
       width: ScreenAdapter.width(750),
       height: ScreenAdapter.width(88),
):LoadingWidget(),

3.3.回到详情页编写接收数据的变量

在这里插入图片描述
导入

import '../../config/Config.dart';
class ProductContentSecond extends StatefulWidget {
  final List _productContentList;
  ProductContentSecond(this._productContentList,{Key key}) : super(key: key);
  _ProductContentSecondState createState() => _ProductContentSecondState();
}

3.4.回到商品页编写接收数据的变量

在这里插入图片描述
ProductContentFirst文件中导入

import '../../model/ProductContentModel.dart';
import '../../config/Config.dart';

class ProductContentFirst extends StatefulWidget {
  final List _productContentList;//--------------------------------
  ProductContentFirst(this._productContentList, {Key key}) : super(key: key);//--------------------------------
  _ProductContentFirstState createState() => _ProductContentFirstState();
}

class _ProductContentFirstState extends State<ProductContentFirst> {
  ProductContentitem _productContent;//--------------------------------

  @override
  void initState() {
    super.initState();
    this._productContent = widget._productContentList[0];
  }

3.5.动态给商品页的属性赋值

在这里插入图片描述
在这里插入图片描述

@override
Widget build(BuildContext context) {
//--------------------------------------------
  //处理图片
  String pic = Config.domain + this._productContent.pic;
  pic = pic.replaceAll('\\', '/');
//--------------------------------------------
  return Container(

child: ListView(
  children: <Widget>[
    AspectRatio(
      aspectRatio: 16 / 12,
      //--------------------------------------------
      child: Image.network("${pic}", fit: BoxFit.cover),
      //--------------------------------------------
    ),
    //标题
    Container(
      padding: EdgeInsets.only(top: 10),
      child: Text
      //--------------------------------------------
		("${this._productContent.title}",
		//--------------------------------------------
          style: TextStyle(
              color: Colors.black87, fontSize: ScreenAdapter.size(36))),
    ),
    Container(
        padding: EdgeInsets.only(top: 10),
        child: Text(
        //--------------------------------------------
        "${this._productContent.subTitle}",
        //--------------------------------------------
            style: TextStyle(
                color: Colors.black54,
                fontSize: ScreenAdapter.size(28)))),
    //价格
children: <Widget>[
  Text("特价: "),
  //--------------------------------------------
  Text("¥${this._productContent.price}",
  //--------------------------------------------
children: <Widget>[
  Text("原价: "),
  //--------------------------------------------
  Text("¥${this._productContent.oldPrice}",
  //--------------------------------------------

3.6.为底部弹框赋值

3.6.0先删除代码

代码在 _attrBottomSheet 封装里面 搜索 mainAxisAlignment: MainAxisAlignment.center,
在这里插入图片描述

创建数组

List _attr = [];

3.6.1为数组赋值

写在 _ProductContentFirstState 里面
在这里插入图片描述

this._attr = this._productContent.attr;

3.6.2封装两个方法

List<Widget> _getAttrItemWidget(attrItem) {
  List<Widget> attrItemList = [];
  attrItem.list.forEach((item) {
    attrItemList.add(Container(
      margin: EdgeInsets.all(10),
      child: Chip(
        label: Text("${item}"),
        padding: EdgeInsets.all(10),
      ),
    ));
  });
  return attrItemList;
}

//封装一个组件 渲染attr
List<Widget> _getAttrWidget() {
  List<Widget> attrList = [];
  this._attr.forEach((attrItem) {
    attrList.add(Wrap(
      children: <Widget>[
        Container(
          width: ScreenAdapter.width(120),
          child: Padding(
            padding: EdgeInsets.only(top: ScreenAdapter.height(22)),
            child: Text("${attrItem.cate}: ",
                style: TextStyle(fontWeight: FontWeight.bold)),
          ),
        ),
        Container(
          width: ScreenAdapter.width(590),
          child: Wrap(
            children: _getAttrItemWidget(attrItem),
          ),
        )
      ],
    ));
  });

  return attrList;
}

3.6.3在底部弹出框调用上面封装的方法。

在这里插入图片描述

padding: EdgeInsets.all(ScreenAdapter.width(20)),
child: ListView(
  children: <Widget>[
    Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: _getAttrWidget()
   )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯汉栩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值