flutter 叮咚买菜UI 测试

本项目 是我用于测试 flutter 各种控件和三方的 demo,为了便于整体的感官效果,于是采用了模仿某咚买菜的小程序 demo,先上一下整体效果预览.

数据是我自己从 APP 上扒下来的,仅做测试效果

ps:顺便要吐槽的是,我扒数据的时候接口返回的还是满28元免赔送,最近我使用叮咚买菜的时候,它竟然涨到了39元免赔送(资本家真是黑心)

接下来,讲讲这个简单的项目采用的技术.

项目SDK 基于">=2.12.0 <3.0.0",全面支持空安全版本,以 Get 为基础框架,做路由管理,状态管理,实现远程路由,本地路由同步,逻辑与界面分离.

下面是你能看到的三方

UI方面

  • 下拉刷新
    pull_to_refresh: ^2.0.0
  • toast
    fluttertoast: ^8.0.7
  • easyloading
    flutter_easyloading: ^3.0.3
  • loading
    loading_animations: ^2.2.0
  • 骨架图
    skeleton_loader: ^2.0.0+4
  • 轮播
    flutter_swiper_null_safety: ^1.0.2

数据方面

  • json序列化
    json_serializable: ^6.1.3
  • 屏幕适配
    flutter_screenutil: ^5.0.0+2
  • 缓存
    shared_preferences: ^2.0.5
  • 设备信息
    device_info: ^2.0.0

框架层面

  • GetX,项目管理框架
    get: ^4.1.4
  • 通过 scheme 打开APP 获取 参数
    uni_links: ^0.5.1

三方这个东西,我从 iOS 开发开始,一直秉持的一个想法就是,前期三方一定要找高星,会持续维护的框架,如果有需要,自己再 fork 一下做局部修改,最好是做持续更新,其他的一些测试性三方我暂时就不发出来了,有条件的可以选择性的自己去重写一些 UI 层的轮子,比如轮播,loading 什么的,练练技术,不过目前我处于 flutter 探索阶段,这一步暂缓.

业务方面

其实也没啥好讲的,业务其实大家都一样,稍微讲讲我做的数据分离吧
以 Category分类页面为例.



index 为 import 入口文件.
view 层逻辑代码为

class CategoryPage extends GetView<CategoryController> {
  const CategoryPage({Key? key}) : super(key: key);

  // 内容页
  Widget _buildView() {
    return Column(
      children: [
        CategoryHeaderView(),
        Container(
          height: 0.1,
          color: Colors.blue,
          child: FittedBox(
            fit: BoxFit.none,
            alignment: Alignment.topCenter,
            child: Container(
                // padding: EdgeInsets.only(top: 10),
                width: ScreenUtil().screenWidth,
                height: 20,
                color: AppColors.lightMain),
          ),
        ),
        Expanded(
          child: Container(
            decoration: BoxDecoration(
              color: Colors.red,
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(10),
                topRight: Radius.circular(10),
              ),
            ),
            clipBehavior: Clip.antiAlias,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Lefter(),
                CategoryDetailListView(),
              ],
            ),
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<CategoryController>(
      init: CategoryController(),
      builder: (_) {
        return Scaffold(
          body: controller.state.isLoad ? _buildView() : skeleton(),
        );
      },
    );
  }
}

可以看到 在 view 层,我使用GetView<CategoryController>去创建页面

abstract class GetView<T> extends StatelessWidget {
  const GetView({Key? key}) : super(key: key);

  final String? tag = null;

  T get controller => GetInstance().find<T>(tag: tag)!;

  @override
  Widget build(BuildContext context);
}

GetView 继承自StatelessWidget,提供了一个 controller 泛型,因为数据完全由 controller 控制刷新,所以我们不需要使用 stful.

controller持有 state,controller 做逻辑处理,state 持有数据

controller

class CategoryController extends GetxController {
  CategoryController();

  final state = CategoryState();

  /// UI 组件
  final RefreshController refreshController = RefreshController(
    initialRefresh: true,
  );

  final ScrollController scrollController = ScrollController();
  final ScrollController headScrollController = ScrollController();

  // tap
  void handleTap(int index) {
    Get.snackbar(
      "标题",
      "消息",
    );
  }

  ***其他业务,数据加载,滚动监听等等***
}

State

state 的数据其实放 controller 也行,但是如果想项目结构更加清晰,可以讲 controller 的数据与逻辑再进行一次分离,分离出一个 state,反正页面刷新都是由 controller 控制的

class CategoryState {
  Category? model;

  CategoryDetail? detail;

  bool isLoad = false;

  /// 是否展示顶部右侧按钮
  bool isHeadAllShow = false;

  // 头部当前选中
  final headCurrentIndex = 0.obs;

  /// 左侧当前选中
  final lefterCurrentIndex = 0.obs;

  /// 透视图
  List<Cate> get headModels => model?.cate ?? [];

  /// 左侧数据
  List<Cate> get lefterModels =>
      headModels.itemNullable(headCurrentIndex.value)?.cate ?? [];

  /// 左侧数据
  List<Product> get righterModels => detail?.products ?? [];
}

由于 category 点击事件都是联动逻辑(头部点击联动左侧数据+右侧详情),所以我大部分使用的是controller.update(),obx 监听在这个页面中没有提现太多使用.(最近拜读了某个大牛的 get 源码解析,对 obx 的认识更深了一步,有机会贴出来一起学习)

这个 demo 其实我也稍微做了一些比较细的小点,比如分类页面头部分类选择时,保证选中的 item 居于最中间,也做了一些动画效果,又比如分类下拉菜单页,做的一个overlayEntry转场进入的选择框效果. 还有首页部分,为了底部的四宫格效果,写了一堆的 array 拖展等等

后续应该不会再对这个叮咚 UI进行 编写了,毕竟是扒的数据,影响不好
我一开始的目的是冲着编写一个flutter快速项目的 脚手架进行的,叮咚的 UI 只是测试 flutter 的 widgetUI 编写,目前这个脚手架还不丰富,三方登录,分享,地图,音视频播放,图片选择,dio 请求,加密,im 业务,数据库缓存,浏览器跳转打开 APP 等等.

所以,后续,我会走两条路子
一是将我所在的公司业务项目利用 flutter,写出"大部分"内容(真实网络请求)
二是继续丰富我的脚手架,顺便做写 demo 测试.

更新不易,如有帮助到各位看官的,点个喜欢, 谢谢啦~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容