建立数据模型层,我们的业务逻辑分开,然后进行后台数据的调试。按照真实项目的开发目录接口和文件组织来进行开发。
建立商品详细模型
我们还是用快速生成的方式建立一下商品详细页的接口模型,有这样一段从后端获取的JSON,直接用快速生成的方式,把这段JSON生成模型,然后进行必要的修改。
{"code":"0","message":"success","data":{"goodInfo":{"image5":"","amount":10000,"image3":"","image4":"","goodsId":"ed675dda49e0445fa769f3d8020ab5e9","isOnline":"yes","image1":"http://images.baixingliangfan.cn/shopGoodsImg/20190116/20190116162618_2924.jpg","image2":"","goodsSerialNumber":"6928804011173","oriPrice":3.00,"presentPrice":2.70,"comPic":"http://images.baixingliangfan.cn/compressedPic/20190116162618_2924.jpg","state":1,"shopId":"402880e860166f3c0160167897d60002","goodsName":"可口可乐500ml/瓶","goodsDetail":"<img src="http://images.baixingliangfan.cn/shopGoodsDetailImg/20171224/20171224081109_5060.jpg" width="100%" height="auto" alt="" /><img src="http://images.baixingliangfan.cn/shopGoodsDetailImg/20171224/20171224081109_1063.jpg" width="100%" height="auto" alt="" /><img src="http://images.baixingliangfan.cn/shopGoodsDetailImg/20171224/20171224081110_8029.jpg" width="100%" height="auto" alt="" /><img src="http://images.baixingliangfan.cn/shopGoodsDetailImg/20171224/20171224081110_1074.jpg" width="100%" height="auto" alt="" /><img src="http://images.baixingliangfan.cn/shopGoodsDetailImg/20171224/20171224081110_8439.jpg" width="100%" height="auto" alt="" /><img src="http://images.baixingliangfan.cn/shopGoodsDetailImg/20171224/20171224081110_6800.jpg" width="100%" height="auto" alt="" />"},"goodComments":[{"SCORE":5,"comments":"果断卸载,2.5个小时才送到","userName":"157******27","discussTime":1539491266336}],"advertesPicture":{"PICTURE_ADDRESS":"http://images.baixingliangfan.cn/advertesPicture/20190113/20190113134955_5825.jpg","TO_PLACE":"1"}}}
复制上面的的代码,代开下面的地址,利用JSON代码,快速生成Model模型。
https://javiercbk.github.io/json_to_dart/
在lib/model
文件夹下新建立details.dart
文件,然后把生成的代码拷贝到下面。
class DetailsModel { String code; String message; DetailsGoodsData data; DetailsModel({this.code, this.message, this.data}); DetailsModel.fromJson(Map<String, dynamic> json) { code = json['code']; message = json['message']; data = json['data'] != null ? new DetailsGoodsData.fromJson(json['data']) : null; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['code'] = this.code; data['message'] = this.message; if (this.data != null) { data['data'] = this.data.toJson(); } return data; } } class DetailsGoodsData { GoodInfo goodInfo; List<GoodComments> goodComments; AdvertesPicture advertesPicture; DetailsGoodsData({this.goodInfo, this.goodComments, this.advertesPicture}); DetailsGoodsData.fromJson(Map<String, dynamic> json) { goodInfo = json['goodInfo'] != null ? new GoodInfo.fromJson(json['goodInfo']) : null; if (json['goodComments'] != null) { goodComments = new List<GoodComments>(); json['goodComments'].forEach((v) { goodComments.add(new GoodComments.fromJson(v)); }); } advertesPicture = json['advertesPicture'] != null ? new AdvertesPicture.fromJson(json['advertesPicture']) : null; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); if (this.goodInfo != null) { data['goodInfo'] = this.goodInfo.toJson(); } if (this.goodComments != null) { data['goodComments'] = this.goodComments.map((v) => v.toJson()).toList(); } if (this.advertesPicture != null) { data['advertesPicture'] = this.advertesPicture.toJson(); } return data; } } class GoodInfo { String image5; int amount; String image3; String image4; String goodsId; String isOnline; String image1; String image2; String goodsSerialNumber; double oriPrice; double presentPrice; String comPic; int state; String shopId; String goodsName; String goodsDetail; GoodInfo( {this.image5, this.amount, this.image3, this.image4, this.goodsId, this.isOnline, this.image1, this.image2, this.goodsSerialNumber, this.oriPrice, this.presentPrice, this.comPic, this.state, this.shopId, this.goodsName, this.goodsDetail}); GoodInfo.fromJson(Map<String, dynamic> json) { image5 = json['image5']; amount = json['amount']; image3 = json['image3']; image4 = json['image4']; goodsId = json['goodsId']; isOnline = json['isOnline']; image1 = json['image1']; image2 = json['image2']; goodsSerialNumber = json['goodsSerialNumber']; oriPrice = json['oriPrice']; presentPrice = json['presentPrice']; comPic = json['comPic']; state = json['state']; shopId = json['shopId']; goodsName = json['goodsName']; goodsDetail = json['goodsDetail']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['image5'] = this.image5; data['amount'] = this.amount; data['image3'] = this.image3; data['image4'] = this.image4; data['goodsId'] = this.goodsId; data['isOnline'] = this.isOnline; data['image1'] = this.image1; data['image2'] = this.image2; data['goodsSerialNumber'] = this.goodsSerialNumber; data['oriPrice'] = this.oriPrice; data['presentPrice'] = this.presentPrice; data['comPic'] = this.comPic; data['state'] = this.state; data['shopId'] = this.shopId; data['goodsName'] = this.goodsName; data['goodsDetail'] = this.goodsDetail; return data; } } class GoodComments { int sCORE; String comments; String userName; int discussTime; GoodComments({this.sCORE, this.comments, this.userName, this.discussTime}); GoodComments.fromJson(Map<String, dynamic> json) { sCORE = json['SCORE']; comments = json['comments']; userName = json['userName']; discussTime = json['discussTime']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['SCORE'] = this.sCORE; data['comments'] = this.comments; data['userName'] = this.userName; data['discussTime'] = this.discussTime; return data; } } class AdvertesPicture { String pICTUREADDRESS; String tOPLACE; AdvertesPicture({this.pICTUREADDRESS, this.tOPLACE}); AdvertesPicture.fromJson(Map<String, dynamic> json) { pICTUREADDRESS = json['PICTURE_ADDRESS']; tOPLACE = json['TO_PLACE']; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); data['PICTURE_ADDRESS'] = this.pICTUREADDRESS; data['TO_PLACE'] = this.tOPLACE; return data; } }
添加商品详情的接口
'getGoodDetailById':serviceUrl+'wxmini/getGoodDetailById',//商品详细信息
Provide建立
在实际开发中,我们是将业务逻辑和UI表现分开的,所以线建立一个Provide文件,所有业务逻辑将写在Provide
里,然后pages
文件夹里只写UI层面的东西。这样就把业务逻辑和UI进行了分离。
在lib/provide/
文件夹下新建立一个details_info.dart
文件,这个文件就是写商品详细页相关的业务逻辑的。
import 'package:flutter/material.dart'; import '../model/details.dart'; import '../service//service_method.dart'; import 'dart:convert/'; class DetailsInfoProvide with ChangeNotifier{ DetailsModel goodsInfo = null; //商品详情的变量 //从后台获取商品数据 getGoodsInfo(String id){ //传递商品id var formData = {'goodId':id}; request('getGoodDetailById', formData: formData).then((val){ var responseData = json.decode(val.toString()); //从后台得到的数据 print(responseData); goodsInfo = DetailsModel.fromJson(responseData); notifyListeners(); //通知 }); } }
先引入刚建立好的Model,然后引入service_method.dart
文件。声明DetailsInfoProvide
l类,在类里边声明一个DetailsModel
类型的 goodsInfo变量,初始值甚至成null,然后写一个从后台获取数据的方法,命名为getGoodsInfo
。
Provide全局注入
在main.dart中注入,先引入details_info.dart文件,然后声明变量、注入
var detailsInfoProvide = DetailsInfoProvide();
..provide(Provider<DetailsInfoProvide>.value(detailsInfoProvide));
在UI调试接口
直接在pages文件夹的details_page.dart
文件里,写一个_getBackInfo
方法,然后在build方法里使用一下。 如果控制台打印出商品详细的数据,说明接口已经调通。
void _getBackInfo(BuildContext context) async{ await Provide.value<DetailsInfoProvide>(context).getGoodsInfo(goodsId); print('加载完成...........'); }
完整代码:
import 'package:flutter/material.dart'; import 'package:provide/provide.dart'; import '../provide/detail_info.dart'; class DetailsPage extends StatelessWidget { final String goodsId; DetailsPage(this.goodsId); //构造函数最新写法 @override Widget build(BuildContext context) { _getBackInfo(context); return Container( child: Center( child: Text('商品ID:${goodsId}'), ), ); } void _getBackInfo(BuildContext context) async{ await Provide.value<DetailsInfoProvide>(context).getGoodsInfo(goodsId); print('加载完成...........'); } }
运行测试,控制台成功打印出商品详细的数据,说明接口已经调通。
详细页UI主页面架构搭建
details_page页面主要修改build
方法。代码如下:
Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( //返回按钮 onPressed: (){ Navigator.pop(context); //返回上级页面 }, icon: Icon(Icons.arrow_back), ), title: Text('商品详细页'), ), body: FutureBuilder( future: _getBackInfo(context), builder: (context, snapshot){ if(snapshot.hasData){ return Container( child: Column( children: <Widget>[ Text('商品ID:${goodsId}') ], ), ); }else{ return Text('加载中......'); } }, ), ); }
在body区域,使用了FutureBuilder Widget
,可以实现异步建在的效果。并且在可以判断snapshot.hasData
进行判断是否在加载还是在加载中。
_getBackInfo方法的修改
在build方法里使用了FutureBuilder
部件,所以使用的后台得到数据的方法,也要相应的做出修改,要最后返回一个Future 部件。代码如下:
Future _getBackInfo(BuildContext context) async{ await Provide.value<DetailsInfoProvide>(context).getGoodsInfo(goodsId); return '完成加载'; }
完整代码如下:
import 'package:flutter/material.dart'; import 'package:provide/provide.dart'; import '../provide/detail_info.dart'; class DetailsPage extends StatelessWidget { final String goodsId; DetailsPage(this.goodsId); //构造函数最新写法 @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( //返回按钮 onPressed: (){ Navigator.pop(context); //返回上级页面 }, icon: Icon(Icons.arrow_back), ), title: Text('商品详细页'), ), body: FutureBuilder( future: _getBackInfo(context), builder: (context, snapshot){ if(snapshot.hasData){ return Container( child: Column( children: <Widget>[ Text('商品ID:${goodsId}') ], ), ); }else{ return Text('加载中......'); } }, ), ); } Future _getBackInfo(BuildContext context) async{ await Provide.value<DetailsInfoProvide>(context).getGoodsInfo(goodsId); return '完成加载'; } }