一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。
效果:
本章目标:
1.创建商品数据模型
2.请求Api接口渲染热门商品
3.获取数据然后用模型赋值给猜你喜欢和热门推荐
第一步:编写全局接口文档
class Config{
static String domain="http://jd.itying.com/";
}
第二步:修改图片轮播器接口 红色这句代码复制修改就可以了
说明:前面的章节接口是整个接口的,现在改为域名+路径
回到home页面进行导入。
import '../../config/Config.dart';
var api = '${Config.domain}api/focus';
第三步:开始编写模型
首先要先拿到接口先 http://jd.itying.com/api/plist?is_best=1 接口里面返回的数据模型是用于热门推荐和猜你喜欢的。
下面的内容是请求http://jd.itying.com/api/plist?is_best=1接口返回的数据,以防将来接口失效可以用下面的数据写成本地。
{"result":[{"_id":"5a0425bc010e711234661439","title":"磨砂牛皮男休闲鞋-有属性","cid":"5a042480010e711234661436","price":"688","old_price":"368","pic":"public\\upload\\RinsvExKu7Ed-ocs_7W1DxYO.png","s_pic":"public\\upload\\RinsvExKu7Ed-ocs_7W1DxYO.png_200x200.png"},{"_id":"5a0432f4010e71123466144c","title":"八匹狼羽绒服男--有属性","cid":"59f1e4f49bfd8f3bd030eed9","price":"288","old_price":"588","pic":"public\\upload\\agbBbaTUWBnWD7pYQOyJsNgJ.png","s_pic":"public\\upload\\agbBbaTUWBnWD7pYQOyJsNgJ.png_200x200.png"},{"_id":"5a07ef1fad8b300e28e2feb6","title":"联想(Lenovo)拯救者R720 15.6英寸游戏笔记本电脑","cid":"59f1e4919bfd8f3bd030eed6","price":"5345","old_price":"5345","pic":"public\\upload\\4i2vxChhbbz2qJMYEUGWw8g_.jpg","s_pic":"public\\upload\\4i2vxChhbbz2qJMYEUGWw8g_.jpg_200x200.jpg"},{"_id":"5a07ef64ad8b300e28e2feb8","title":"神舟(HASEE)战神K650D-G4D2 15.6英寸游戏笔记本电脑","cid":"59f1e4919bfd8f3bd030eed6","price":"4500","old_price":"4500","pic":"public\\upload\\iG8QZV0x7Thh8ZFKA3bCTER5.jpg","s_pic":"public\\upload\\iG8QZV0x7Thh8ZFKA3bCTER5.jpg_200x200.jpg"},{"_id":"5a07efe9ad8b300e28e2febb","title":"戴尔DELL灵越游匣Master15-R4645R 15.6英寸游戏笔记本电脑","cid":"59f1e4919bfd8f3bd030eed6","price":5677,"old_price":"6778","pic":"public\\upload\\YUv6N37Lriv7QK7WePQmyz-u.jpg","s_pic":"public\\upload\\YUv6N37Lriv7QK7WePQmyz-u.jpg_200x200.jpg"},{"_id":"5a080a05ad8b300e28e2fec1","title":"小米 红米Note5A 全网通版 2GB+16GB 香槟金 移动联通电信4G手机 双卡双待","cid":"59f1e4919bfd8f3bd030eed6","price":688,"old_price":"688","pic":"public\\upload\\1X_pUZmj8jQrVrWeiRtoa4Zx.jpg","s_pic":"public\\upload\\1X_pUZmj8jQrVrWeiRtoa4Zx.jpg_200x200.jpg"},{"_id":"5a080a9fad8b300e28e2fec6","title":"荣耀 畅玩6X 4GB 32GB 全网通4G手机 高配版 玫瑰金","cid":"59f1e4919bfd8f3bd030eed6","price":"789","old_price":"11111","pic":"public\\upload\\HSAZYh1vXyzn3kvpso4fs7iT.jpg","s_pic":"public\\upload\\HSAZYh1vXyzn3kvpso4fs7iT.jpg_200x200.jpg"},{"_id":"5a080ac5ad8b300e28e2fec7","title":"三星 Galaxy S7 edge(G9350)4GB+32GB 铂光金 移动联通电信4G手机","cid":"59f1e4919bfd8f3bd030eed6","price":1233,"old_price":"1322","pic":"public\\upload\\SesgdVtaD0RzW2B5NKXcTmEK.jpg","s_pic":"public\\upload\\SesgdVtaD0RzW2B5NKXcTmEK.jpg_200x200.jpg"},{"_id":"5a080b2ead8b300e28e2fec9","title":"小米Max2 全网通 4GB+64GB 金色 移动联通电信4G手机 双卡双待 6.44英寸大","cid":"59f1e4919bfd8f3bd030eed6","price":980,"old_price":"1211","pic":"public\\upload\\e7Z7qLeDpyFjNZMF2Ke1aiTE.jpg","s_pic":"public\\upload\\e7Z7qLeDpyFjNZMF2Ke1aiTE.jpg_200x200.jpg"},{"_id":"5a080c2ead8b300e28e2fed1","title":"锤子 坚果Pro 64GB 酒红色 全网通 移动联通电信4G手机 双卡双待 火热抢购中,","cid":"59f1e4919bfd8f3bd030eed6","price":1456,"old_price":"1468","pic":"public\\upload\\E8jnbcercoZGdllR3r9QN5aD.jpg","s_pic":"public\\upload\\E8jnbcercoZGdllR3r9QN5aD.jpg_200x200.jpg"}]}
拿到接口请求数据回来,然后打开 https://jsontodart.com/ 去自动生成Model 如果网站丢失就去百度输入JsonToDart 搜索。
模型名称为 ProductModel
在ProductModel模型中需要注意的是必须要修改一个地方,不然项目运行会崩溃
网上生成的模型多数是string类型,需要自己手动修改一下。
Object price; //所有的类型都继承 Object
最终模型代码:
class ProductModel {
List<ProductItemModel> result;
ProductModel({this.result});
ProductModel.fromJson(Map<String, dynamic> json) {
if (json['result'] != null) {
result = new List<ProductItemModel>();
json['result'].forEach((v) {
result.add(new ProductItemModel.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.result != null) {
data['result'] = this.result.map((v) => v.toJson()).toList();
}
return data;
}
}
class ProductItemModel {
String sId;
String title;
String cid;
Object price;
String oldPrice;
String pic;
String sPic;
ProductItemModel(
{this.sId,
this.title,
this.cid,
this.price,
this.oldPrice,
this.pic,
this.sPic});
ProductItemModel.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
title = json['title'];
cid = json['cid'];
price = json['price'];
oldPrice = json['old_price'];
pic = json['pic'];
sPic = json['s_pic'];
}
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['pic'] = this.pic;
data['s_pic'] = this.sPic;
return data;
}
}
第四步:在首页中编写代码
1.导入模型
//热门跟推荐模型
import '../../model/ProductModel.dart';
// import 'package:review_flutter_app/model/ProductModel.dart';
2.创建接收model的数组
List _hotProductList = [];
List _bestProductList = [];
3.编写获取数据的方法
//获取猜你喜欢的数据
_getHotProductData() async {
//编写接口
var api = '${Config.domain}api/plist?is_hot=1';
//请求数据
var result = await Dio().get(api);
//格式化数据
var hotProductList = ProductModel.fromJson(result.data);
//更新UI
setState(() {
this._hotProductList = hotProductList.result;
});
}
//获取热门推荐的数据
_getBestProductData() async {
//编写接口
var api = '${Config.domain}api/plist?is_best=1';
//请求数据
var result = await Dio().get(api);
//格式化数据
var bestProductList = ProductModel.fromJson(result.data);
//更新UI
setState(() {
this._bestProductList = bestProductList.result;
});
}
第五步:程序启动时调用该方法
_getHotProductData();
_getBestProductData();
把上面的这两句代码写到下面的图片中,页面进来就请求接口,获取数据。
第六步:UI中赋值
源码
//热门商品
Widget _hotProductListWidget() {
if (this._hotProductList.length > 0){
return Container(
height: ScreenAdaper.height(234),
padding: EdgeInsets.all(ScreenAdaper.width(20)),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
//处理图片
String sPic = this._hotProductList[index].sPic;//——————————---------
sPic = Config.domain + sPic.replaceAll('\\', '/');//——————————---------
return Column(
children: <Widget>[
Container(
height: ScreenAdaper.height(140),
width: ScreenAdaper.width(140),
margin: EdgeInsets.only(right: ScreenAdaper.width(21)),
child: Image.network(
sPic,//——————————---------
fit: BoxFit.cover,
),
),
Container(
padding: EdgeInsets.only(top: ScreenAdaper.width(10)),
height: ScreenAdaper.height(44),
child: Text(//——————————---------
'¥${this._hotProductList[index].price}',//——————————---------
style: TextStyle(color: Colors.red),//——————————---------
),//——————————---------
),
],
);
}),
);
}else{//——————————---------
return Text('记载中....');//——————————---------
}//——————————---------
}
热门推荐商品
Widget _recProductItemWidget() {
var itemWidth = (ScreenAdaper.getScreenWidth() - 30) / 2; //计算容器宽度大小
return Container(
padding: EdgeInsets.all(10),
child: Wrap(
runSpacing: 10,
spacing: 10,
children: this._bestProductList.map((value){
//图片
String sPic=value.sPic;//—————————————————————————————————
sPic=Config.domain+sPic.replaceAll('\\', '/');//—————————————————————————————————
return Container(
padding: EdgeInsets.all(10), //设置容器内边框为10
width: itemWidth, //设置每个小容器的宽度
decoration: BoxDecoration(
//设置边框
border: Border.all(
color: Color.fromRGBO(233, 233, 233, 0.9), width: 1), //设置边框颜色跟变宽宽度
),
child: Column(
children: <Widget>[
Container(
//添加容器抱住图片,目的是可以设置图片与最大容器之前的宽高比
width: double.infinity,
child: AspectRatio(
aspectRatio: 1 / 1,
child: Image.network(
"${sPic}",//—————————————————————————————————
fit: BoxFit.cover,
),
),
),
Padding(
//添加外边框抱住文字,目的是可以让文字与上面的图片有一个顶部距离20
padding: EdgeInsets.only(top: ScreenAdaper.height(20)),
child: Text(
"${value.title}",//—————————————————————————————————
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.black54),
),
),
Padding(
//添加外边框抱住文字,目的是可以让文字与上面的图片有一个顶部距离20
padding: EdgeInsets.only(top: ScreenAdaper.height(20)),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.centerLeft, //控件在框的左边
child: Text(
"¥${value.price}",//—————————————————————————————————
style: TextStyle(color: Colors.red, fontSize: 16),
),
),
Align(
alignment: Alignment.centerRight, //控件在框的右边
child: Text(
"¥${value.oldPrice}",//—————————————————————————————————
style: TextStyle(
color: Colors.black54,
fontSize: 14,
decoration: TextDecoration.lineThrough, //文字中间加下划线
),
),
),
],
),
),
],
),
);
}).toList(),
),
);
}
4.不过要注意的是热门推荐UI的结构要修改一下
(下面的内容看看就可以了,不用写)
@override
Widget build(BuildContext context) {
ScreenAdaper.init(context);
// TODO: implement build
return ListView(
children: <Widget>[
_swiperWidget(),
SizedBox(
height: ScreenAdaper.height(10),
),
_titleWidge('猜你喜欢'),
SizedBox(
height: ScreenAdaper.height(10),
),
_hotProductListWidget(),
SizedBox(
height: ScreenAdaper.height(10),
),
_titleWidge('热门推荐'),
_recProductItemWidget(),
],
);
}
}