Flutter|解耦初實(shí)踐

本文提出了一個簡單的Flutter解耦demo

背景

社區(qū)目前同時接入了兩個游戲業(yè)務(wù)剑梳,在上一篇文章社區(qū)SDK多業(yè)務(wù)適配(業(yè)務(wù)層)也介紹了一些業(yè)務(wù)層的多業(yè)務(wù)適配手段。通過模塊化去定制功能可以有效避免業(yè)務(wù)間相互干擾焦匈,但對于通用功能包括UI的區(qū)別還只是逐個判斷抖格。

隨著版本迭代票堵,還要支持豎屏能力(如圖)攘宙,多業(yè)務(wù)x橫豎屏導(dǎo)致適配復(fù)雜度加大坦弟,不同點(diǎn)越多越難適配蜗细;而且Flutter的嵌套式寫法將UI和邏輯放在一起裆操,哪怕只是UI小細(xì)節(jié)的不同也要用if-else區(qū)分,這種寫法使得可讀性比較差,維護(hù)成本變高踪区,容易出錯昆烁。

在產(chǎn)品策略和設(shè)計(jì)層雖然有盡量保持通用能力一致但還有各有風(fēng)格,細(xì)節(jié)差異也不少朽缴,所以技術(shù)上做解耦還是很有必要的善玫。

方案

最關(guān)鍵一步就是將Flutter嵌套寫法中的UI和邏輯分離,即原來 Widget(UI密强、交互茅郎、數(shù)據(jù)) 變成 Cell = View(UI)+ ViewModel (交互) + 數(shù)據(jù)。這里用到了狀態(tài)管理庫Riverpod或渤,與 Provider 類似系冗,通過 Provider 和 Consumer 來實(shí)現(xiàn)狀態(tài)管理,通過依賴注入的方式來共享和訪問狀態(tài)薪鹦,相比Provider 使用上更簡單直觀掌敬、可擴(kuò)展更強(qiáng)、提供更好的異步狀態(tài)管理支持池磁。

首先添加依賴項(xiàng):

flutter_riverpod: ^2.3.6

然后創(chuàng)建一個全局狀態(tài)容器:

void main() {
  runApp(ProviderScope(child: MyApp()));
}

接下來就是改造后的幾個主要成員奔害,首先是Cell類,綁定了對應(yīng)的View和ViewModel地熄,除了常用的build繪制华临,還支持在initStatedispose做一些初始化和銷毀的操作:

import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'base_provider.dart';
import 'base_view_model.dart';

abstract class BaseCell<VM extends BaseViewModel>
    extends ConsumerStatefulWidget {
  late BaseVMProvider<VM> provider;
  late Widget Function(BuildContext context, VM value) builder;

  BaseCell({super.key}) {
    this.provider = getVMProvider();
    this.builder = getView();
  }

  BaseVMProvider<VM> getVMProvider();

  Widget Function(BuildContext context, VM vm) getView();

  Function(VM vm)? onInitState() {
    return null;
  }

  Function(VM vm)? onDispose() {
    return null;
  }

  @override
  ConsumerState<BaseCell> createState() => BaseCellState<VM>();
}

class BaseCellState<VM extends BaseViewModel>
    extends ConsumerState<BaseCell<VM>> {
  @override
  void initState() {
    super.initState();
    widget.onInitState()?.call(ref.read(widget.provider));
  }

  @override
  void dispose() {
    widget.onDispose()?.call(ref.read(widget.provider));
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(context, ref.watch(widget.provider));
  }
}

View類主要有一個ViewModel來處理除UI部分的功能:

import 'package:flutter/material.dart';

import 'base_view_model.dart';

abstract class BaseView<VM extends BaseViewModel> extends StatelessWidget {
  final VM vm;

  BaseView(this.vm);
}

ViewModel類主要是一個通知View做UI更新的接口:

import 'package:flutter/cupertino.dart';

abstract class BaseViewModel extends ChangeNotifier {
  @protected
  void refreshUI(Function block) {
    block();
    if (hasListeners) {
      notifyListeners();
    }
  }
}

通用的狀態(tài)生成器:

import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

typedef BaseVMProvider<T extends ChangeNotifier>
= AutoDisposeChangeNotifierProvider<T>;

typedef BaseVMRef<T extends ChangeNotifier>
= AutoDisposeChangeNotifierProviderRef<T>;

class BaseVMProviderFactory {
  static BaseVMProvider<T> create<T extends ChangeNotifier>(
      T Function(BaseVMRef<T> ref) create) {
    return ChangeNotifierProvider.autoDispose<T>((ref) {
      return create(ref);
    });
  }
}

舉個簡單的使用例子,模擬請求返回?cái)?shù)據(jù)后刷新界面:

目前只是一個初步demo端考,還需要具體實(shí)踐下來不斷完善雅潭,這種解耦思路還是可以參考的。

總結(jié)

如此却特,在定制橫豎屏或不同業(yè)務(wù)的樣式只要繼承復(fù)寫View即可扶供,無需改動邏輯部分,使得適配過程更加高效和可靠裂明。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椿浓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子闽晦,更是在濱河造成了極大的恐慌轰绵,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,207評論 6 521
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尼荆,死亡現(xiàn)場離奇詭異,居然都是意外死亡唧垦,警方通過查閱死者的電腦和手機(jī)捅儒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,455評論 3 400
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巧还,你說我怎么就攤上這事鞭莽。” “怎么了麸祷?”我有些...
    開封第一講書人閱讀 170,031評論 0 366
  • 文/不壞的土叔 我叫張陵澎怒,是天一觀的道長。 經(jīng)常有香客問我阶牍,道長喷面,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,334評論 1 300
  • 正文 為了忘掉前任走孽,我火速辦了婚禮惧辈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磕瓷。我一直安慰自己盒齿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,322評論 6 398
  • 文/花漫 我一把揭開白布困食。 她就那樣靜靜地躺著边翁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪硕盹。 梳的紋絲不亂的頭發(fā)上符匾,一...
    開封第一講書人閱讀 52,895評論 1 314
  • 那天,我揣著相機(jī)與錄音莱睁,去河邊找鬼待讳。 笑死,一個胖子當(dāng)著我的面吹牛仰剿,可吹牛的內(nèi)容都是我干的创淡。 我是一名探鬼主播,決...
    沈念sama閱讀 41,300評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼南吮,長吁一口氣:“原來是場噩夢啊……” “哼琳彩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起部凑,我...
    開封第一講書人閱讀 40,264評論 0 277
  • 序言:老撾萬榮一對情侶失蹤露乏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涂邀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘟仿,經(jīng)...
    沈念sama閱讀 46,784評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,870評論 3 343
  • 正文 我和宋清朗相戀三年比勉,在試婚紗的時候發(fā)現(xiàn)自己被綠了劳较。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驹止。...
    茶點(diǎn)故事閱讀 40,989評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖观蜗,靈堂內(nèi)的尸體忽然破棺而出臊恋,到底是詐尸還是另有隱情,我是刑警寧澤墓捻,帶...
    沈念sama閱讀 36,649評論 5 351
  • 正文 年R本政府宣布抖仅,位于F島的核電站,受9級特大地震影響砖第,放射性物質(zhì)發(fā)生泄漏撤卢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,331評論 3 336
  • 文/蒙蒙 一厂画、第九天 我趴在偏房一處隱蔽的房頂上張望凸丸。 院中可真熱鬧,春花似錦袱院、人聲如沸屎慢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,814評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腻惠。三九已至,卻和暖如春欲虚,著一層夾襖步出監(jiān)牢的瞬間集灌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,940評論 1 275
  • 我被黑心中介騙來泰國打工复哆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留欣喧,地道東北人。 一個月前我還...
    沈念sama閱讀 49,452評論 3 379
  • 正文 我出身青樓梯找,卻偏偏與公主長得像唆阿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锈锤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,995評論 2 361

推薦閱讀更多精彩內(nèi)容