从 0 开始设计 Flutter 独立 APP | 第一篇: 数据库与状态管理 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
请不要在回答技术问题时复制粘贴 AI 生成的内容
vifird

从 0 开始设计 Flutter 独立 APP | 第一篇: 数据库与状态管理

  •  
  •   vifird Jun 18, 2020 3002 views
    This topic created in 2146 days ago, the information mentioned may be changed or developed.

    鉴于 Flutter 高性能渲染和跨平台的优势,闪点清单在移动端 APP 上,使用了完整的 Flutter 框架来开发。既然是完整 APP,架构搭建完全不受历史 Native APP 的影响,没有历史包袱的沉淀,设计也能更灵活和健壮。

    Flutter

    首先列举部分闪点清单的业务特性(较为通用的业务特性):

    1. 本地有较大数据量的清单数据,离线可用,未登录可用;登录后需要服务器数据同步
    2. 状态变更场景多,前端状态逻辑较为复杂,跨页面、跨组件状态更新频繁

    这几个业务点,设计到的技术选型有:本地数据库、前端状态管理,对很多业务来说,这几点都是比较核心的东西,也是我们今天重点要讲的内容。

    数据库选型

    数据库选型,首先要定的,就是选择数据库类型:关系型数据库、非关系型数据库还是 Key/Value 存储。

    对于关系型数据库,可选的有比如:SQLite 、Core Data 、GreenDao 等;对于非关系型数据库,可选有 Realm 、UnQLite 等;对于 Key/Value 存储,有比如 Redis 、Berkeley DB 、Level DB 等。

    由于业务形态具有复杂的查询场景,所以首先排除了 Key/Value 存储;然后鉴于业务迭代频繁,数据结构变动较大,所以完全的关系型数据库使用成本会较高,版本更新时在数据兼容和数据清洗方面要做较多的工作;所以我们采用了 NoSQL 数据库,或者支持 JSON 类型的关系型数据库。

    Flutter 目前在 NoSQL 上的可选项并不多,Realm 、UnQLite 等均未支持(当然可以通过 Flutter FFI 来封装给 Dart 用,但成本过高); Flutter 的 sqflite 插件可以较好地支持 SQLite,但由于 SQLite 在 3.9 以后才支持 JSON 数据,考虑到 Android 版本(Android 各版本使用的 SQLite 版本文档)兼容问题,我们并没有采用 sqflite ;我们最终采用的数据库是Sembast,一个还比较小众,但性能和 API 建设都还不错的 NoSQL 数据库。

    Flutter

    Sembast 介绍

    Sembast API 很简洁,但能支持较复杂的数据库操作。 在数据查询上,能够通过简单的逻辑 API,通过聚合构造出复杂的逻辑查询语句;数据排序实现也比较完整,支持多字段排序(但不支持 bool 类型排序);对事务操作也有支持;支持整型自增 key 。

    Sembast 部分 API 预览

    var store = intMapStoreFactory.store('animas'); // 事务处理 await db.transaction((txn) async { await store.add(txn, {'name': 'fish'}); await store.add(txn, {'name': 'cat'}); await store.add(txn, {'name': 'dog'}); }); // 数据查询 var finder = Finder( filter: Filter.greaterThan('name', 'cat'), sortOrders: [SortOrder('name')]); var records = await store.find(db, finder: finder); expect(records.length, 2); expect(records[0]['name'], 'dog'); expect(records[1]['name'], 'fish'); 

    但由于对小众数据库前途的担忧考虑,我们设计了便于迁移的数据架构,对数据操作层做了一层抽象,后期如果迁移数据库,业务层可以完全不需要改动。

    状态管理选型

    状态管理,在如今的前端技术中,是非常重要的一环,好的状态管理框架,可以让业务更好得解耦、简化组件数据通讯成本、大幅提升开发体验。我们在状态管理选型上花了较多的时间来对比各种方案,比如:providerblocreduxscoped_modelmobx、甚至业界网红团队的fish-redux。我们最终采用的是 mobx,关于各个方案的对比,一篇文章讲不完,我们最终选择 mobx,更多是因为它的 API 更友好。

    Mobx 采用注解的方式来定义状态,并封装了一个 Widget 用于 Widget 的数据更新,学习、使用成本较低。

    Tech

    注解定义

    Mobx 的注解使用方式,与 Web 中的 Vue 非常类似如:

    1. 使用 @observable 来注解一个属性,表示其需要被监听,Mobx 会自动为其添加 getter 和 setter
    2. 使用 @computed 来注解一个计算属性
    3. 使用 @action 来注解一个修改 store 的方法,类似于 Vuex 里的 mutations

    示例代码:

    import 'package:mobx/mobx.dart'; part 'counter.g.dart'; class Counter = CounterBase with _$Counter; abstract class CounterBase with Store { @observable int value = 0; @computed int get allowCount { return value*2; } @action void increment() { value++; } } 

    使用 Mobx 必须的一个步骤,就是前置编译步骤。我们编写 Mobx 的状态脚本,需要在前置编译环节,编译成 dart 可读的脚本,为此我们需要执行flutter pub run build_runner build生成.g.dart为后缀的文件(其实就是将注解转义为 getter 和 setter )。 UI 更新方式

    UI 更新方式

    需要使用 Mobx 的 Widget,使用 Observer 包装一层,这样其就可以相应 Mobx 的状态变化,如:

    Observer( builder: (context) => Text('昵称: ${userStore.user.username}'), ) 

    前置编译脚本

    Dart 在编译时和运行时均无法支持注解,所以 Mobx 使用了前置编译脚本解析注解动态生成 Dart 代码的方式( Dart 官方支持)。Mobx 注解方式使用前,需要为项目添加build_runnermobx_codegen依赖。build_runner为 Dart 官方提供,用于在构建项目之前执行特定任务,任务配置于依赖库的build.yaml脚本中; mobx_codegen依赖于该build_runner将注解生成可执行的 Dart 代码(如添加 getter 和 setter 方法)。

    结尾

    状态管理和数据库,是前端项目基础框架的重要环节,设计好了可以很好地提升开发体验和效率,降低后续开发维护成本。

    讲到这里,还并没有完成基础框架的搭建,后面我们会讲解更多的 Flutter 架构设计内容,比如:国际化、通知、分享、UI 设计等等。


    持续分享闪点清单在 Flutter 上的开发经验,闪点清单移动端 APP 体验:

    硬广,很硬

    闪点清单PC 端 APP: 业界唯一一款悬浮清单软件

    闪点清单移动端 APP:

    Supplement 1    Jun 19, 2020

    闪点清单,一款悬浮清单软件

    4 replies    2020-06-20 00:11:33 +08:00
    weixiangzhe
        1
    weixiangzhe  
       Jun 18, 2020 via Android
    支持一下
    JormunChan
        2
    JormunChan  
       Jun 18, 2020
    马克一下
    vifird
        3
    vifird  
    OP
       Jun 20, 2020
    @weixiangzhe 感谢感谢
    vifird
        4
    vifird  
    OP
       Jun 20, 2020
    @JormunChan 感谢感谢
    About     Help     Advertise     Blog     API     FAQ     Solana     2480 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 01:05 PVG 09:05 LAX 18:05 JFK 21:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86