從0開始設計Flutter獨立APP | 第一篇: 數據庫與狀態管理

鑑於Flutter高性能渲染和跨平臺的優點,閃點清單在移動端APP上,使用了完整的Flutter框架來開發。既然是完整APP,架構搭建徹底不受歷史Native APP的影響,沒有歷史包袱的沉澱,設計也能更靈活和健壯。前端

Flutter

首先列舉部分閃點清單的業務特性(較爲通用的業務特性):android

  1. 本地有較大數據量的清單數據,離線可用,未登陸可用;登陸後須要服務器數據同步
  2. 狀態變動場景多,前端狀態邏輯較爲複雜,跨頁面、跨組件狀態更新頻繁

這幾個業務點,設計到的技術選型有:本地數據庫、前端狀態管理,對不少業務來講,這幾點都是比較核心的東西,也是咱們今天重點要講的內容。git

數據庫選型

數據庫選型,首先要定的,就是選擇數據庫類型:關係型數據庫、非關係型數據庫仍是Key/Value存儲。github

對於關係型數據庫,可選的有好比:SQLite、Core Data、GreenDao等;對於非關係型數據庫,可選有Realm、UnQLite等;對於Key/Value存儲,有好比Redis、Berkeley DB、Level DB等。sql

因爲業務形態具備複雜的查詢場景,因此首先排除了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數據庫。redux

Flutter

Sembast介紹服務器

Sembast API很簡潔,但能支持較複雜的數據庫操做。 在數據查詢上,可以經過簡單的邏輯API,經過聚合構造出複雜的邏輯查詢語句;數據排序實現也比較完整,支持多字段排序(但不支持bool類型排序);對事務操做也有支持;支持整型自增key。數據結構

Sembast部分API預覽架構

var store = intMapStoreFactory.store('animals');

// 事務處理
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:

相關文章
相關標籤/搜索