Flutter从入门到写出完整App Day15
20.4.3 五
项目架构搭建, 首页搭建
展示内容, 读取JSON文件
加个类前缀做区分
首页代码改进
抽到一个Widget里面, 减少嵌套层级
有时候快捷键抽取有时并不是特别好
依赖的东西太多了
一些东西会作为参数放在里面
依赖数组, 会把整个数组传给我们
home_category_item.dart
冗余代码
StatefulWidget 定义变量 加载数据
新的知识点
继承StatelessWidget
异步加载数据, 根据异步加载的数据进行展示
=> FutureBuilder
未来构建的东西, 网络请求, 有数据的时候构建对应界面
两个必传参数
future: 发送的异步请求
builder: (ctx, snapshot) {
return
}
没有数据展示加载中, 加载完了之后再展示
=> snapshot.hasData
snapshot.data 泛型类, 上面就写好具体类型
请求失败有error
if (snapshot.error) return Center(child: Text("请求失败"));
局限性
不是所有场景都适用
Container/padding
上拉加载更多
传过来参数 page: 1
page的值不断地变化
一些场景下只能用StatefulWidget
下一个页面,
加载json文件
meal.json
服务器请求
123.207.32.32:9001/api/meal
数据在多个地方进行共享
加载多次数据没必要
把数据加载一次, 放在一个共同的地方共享
过滤出来你想要的数据
=> Provider => ViewModel
思路: 服务器 -> 网络请求 -> 数据共享
之前封装的网络请求工具类
依赖dio
meal_request.dart文件
静态方法 static
- 发送网络请求
- json转modal
网站转换, 数据特别复杂的时候转换的有问题
女装商城数据, 电商
123.207.32.32:8000/api/h3/detail?iid=1lwwv82
使用网站转换, 报一大堆错误,
生成了一个类 List, DartCore里面有List
给另一个网站, 更有效
各种语言的模型都可以转换
app.quicktype.io
这次的模型没有报错, 可以直接用
还生成了两个全局函数模型json互转
拿到的数据放到对应的ViewModel中
对数据做一个共享
=> Provider官方维护, 添加相关依赖
Provider -> ViewModel/Provider/Consumer(Selector)
MVVM
viewmodel文件夹
meal_view_model.dart文件
class JHMealViewModel extends ChangeNotifier
Provider
ChangeNotifierProvier(
create:
child: MyApp()
)
懒加载, 不影响首屏加载数据
数据间的关系Category和Meal
模型传递到下一个页面
category: id -> meals 过滤
监听点击, 首页Item点击
懒加载, 没有打印"请求拦截"
导入引用
结构清晰
ModalRoute.of(context), 拿到的是栈顶层的路由传递的参数
拿到的是同一个, 重新拿或传过来都行
Consumer拿到的是ViewModel
高阶函数做锅炉类似filter
where((meal) => meal.categories.contains(category.id))
拿到的meals不是数组类型, 是一个抽象类
转成toList
不想用Consumer
- 只要是数据发生改变, 必然重新构建
- 现在的过滤, 直接的过滤
换成Selector
Selector<JHMealViewModel(原始数据), List<JHMealModel>>
要写两个泛型
必传参数
selector: 前面是上下文ctx, 用来做过滤 A传进来, 做各种转化, 最后返回S
(mealVM) => mealVM.meals.where((meal) => )
箭头函数可以写开
shouldRebuild: (prev, next) =>
包含的数据不同, 才进行刷新
两个List
List<JHMealModel> prev = ["abc", "cba", ];
List<JHMealModel> next = [""];
- 遍历, 把其中一个遍历一下
=> 查了一下API, 专门比较两个列表
-> import '.../collection.dart';
不同的时候需要重新刷新 !ListEquality().equals(prev, next),
builder: (ctx, meals, child) {
return ListView.builder(
itemCount:meals.length,
itemBuilder: (ctx, index) {
return ListTile();
}
);
}
=>封装一个Widget
meal_item.dart
暂时没有数据改变 => StatelessWidget
Card的效果比较好看
Column
Stack 存在层叠
Row
先分清结构再写布局
Card有个margin: EdgeInsets.all(10.px),
阴影elevation: 5,
很多东西不需要记, 经常点到源码看继承关系
图片没有圆角, 问题,
稍微复杂一点的东西, 图片下面没有圆角, 上面有圆角
=> 图片进行裁剪
又是一个新的API, 单独裁剪某些圆角
BorderRadius.only(
topLeft: Radius.circular(12.px),
)
Positioned()绝对定位
会在多个地方用到的, 单独封装一个Widget
operation_item.dart
class JHOperationItem extends StalessWidget{}
显示简单和复杂
complexity: 0, 数据中的复杂程度 0, 1, 2
搞一个字符串类型, 创建模型的时候, 直接赋值过去一个值
一个简单的方法
List<String> complexs = ["简单", ...]; 0,1,2
不是从0开始就别这样干
确定没有问题报警告, moreAction, 保存单词到字典里面
再稍微讲一会
当点击Card时, 跳转到一个详情页面
detail.dart
Card默认没有点击事件, 监听点击, 手势
一般放到最后
改路由的东西需要HotRestart