Flutter框架 進階一 Flutter-Habit 框架

Flutter-Habit誕生

Flutter-Habit
本文主要講解,F(xiàn)lutter-Habit架構(gòu)圖解,全文架構(gòu)盹愚,完全參照Android目前最流行的MVVM+DataBinding方式封裝茉稠,目的旨在讓客戶端人員更加友好理解Flutter-Habit框架歼捐,進而能夠進入快速開發(fā)

Flutter-基礎(chǔ)功能拆解

  • base–提供基礎(chǔ)組件蔬螟,如缺省頁厅各,基礎(chǔ)容器
  • constants–提供全局使用的常量盗蟆、屬性
  • helper–跨組件的全局屬性
  • local–本地存儲
  • network–網(wǎng)絡(luò)管理戈二,包括加解密
  • localizetion–多語言管理
  • utlis–工具類
  • widget–自定義控件
  • constant-config 配置文件
  • habit 插件交互管理
  • view_model 對外暴露
Flutter 核心功能講解
  • BaseScaffold包括了幾個核心的功能
    1.全局的ToolBar設(shè)置控制
  /// 設(shè)置ToolBar
  final Widget toolBar;

同時提供默認的ToolBar Widget

/// 獲取當前的Toolbar的參數(shù)
  Widget _findCurrentToolBar() {
    /// 優(yōu)先顯示設(shè)置的toolBar
    if (widget.toolBar != null) {
      return widget.toolBar;
    }

    /// 顯示默認的toolbar
    if (widget.toolBar == null && widget.viewModel.appBarIsShow) {
      return AppBarWidget(widget.viewModel);
    }
    return null;
  }

2.全局缺省頁控制以及自定義

GestureDetector(
          behavior: HitTestBehavior.translucent,
          onTap: () {
            KeyboardUtils.hideByContext(context);
          },
          child: ValueListenableBuilder<EmptyState>(
            valueListenable: widget.viewModel.emptyState,
            builder: (context, state, _) => state == EmptyState.NORMAL
                ? widget.body
                : BaseEmptyStateWidget<VM>(
                    toolBar: widget.toolBar,
                  ),
          ),
        )

3.生命周期的監(jiān)聽

///頁面生命周期
enum PageState {
  RESUMED,
  INACTIVE,
  PAUSED,
  DETACHED,
}
聲明頁面的生命周期,進行相關(guān)業(yè)務(wù)開發(fā)

由于本文基于Android Mvvm+Databinding模式進行Flutter開發(fā)喳资,所以觉吭,這里數(shù)據(jù)監(jiān)聽方式使用的是ValueNotifier,以下以AppBarWidget進行一個簡單描述

import 'package:flutter/material.dart';
import 'package:habit/example/widget/base_view_model.dart';
import 'package:habit/habit.dart';

///全局的ToolBar
class AppBarWidget extends StatelessWidget with PreferredSizeWidget {
  final BaseViewModel appBarProperty;

  AppBarWidget(this.appBarProperty);

  @override
  Widget build(BuildContext context) {
    return ValueListenableListBuilder(
      valueListenables: [
        appBarProperty.appBarTitle,
        appBarProperty.appBarShowBackIcon,
        appBarProperty.appBarBackIconColor,
        appBarProperty.appBarTitleColor,
        appBarProperty.appBarTitleSize,
        appBarProperty.appBarBgColor,
        appBarProperty.appBarBrightness,
        // appBarProperty.appBarLeadingCallBack
      ],
      builder: (context, value, child) {
        return AppBar(
          brightness: appBarProperty.appBarBrightness.value,
          backgroundColor: appBarProperty.appBarBgColor.value==null
              ? Theme.of(context).accentColor
              : appBarProperty.appBarBgColor.value,
          elevation: 0,
          centerTitle: true,
          title: Text(
            appBarProperty.appBarTitle.value,
            style: TextStyle(
              fontSize: appBarProperty.appBarTitleSize.value,
              color: appBarProperty.appBarTitleColor.value,
              fontWeight: FontWeight.bold,
            ),
          ),
          leading: Visibility(
            visible: appBarProperty.appBarShowBackIcon.value,
            child: IconButton(
              onPressed: () {
                // appBarProperty.appBarLeadingCallBack.value?.call();
                ///執(zhí)行默認的返回按鈕
                if (appBarProperty.appBarLeadingCallBack.value == null) {
                  Navigator.pop(context);
                } else {
                  appBarProperty.appBarLeadingCallBack.value.call();
                }
              },
              icon: Icon(
                Icons.arrow_back,
                color: appBarProperty.appBarBackIconColor.value,
                size: 25,
              ),
            ),
          ),
        );
      },
    );
  }

  @override
  Size get preferredSize => AppBar().preferredSize;
}

全文重點在于ValueListenableListBuilder骨饿,直接上源碼

class ValueListenableListBuilder<T> extends StatefulWidget {
  const ValueListenableListBuilder({
    Key key,
    @required this.valueListenables,
    @required this.builder,
    this.child,
  })  : assert(valueListenables != null),
        assert(builder != null),
        super(key: key);
  ///看這里亏栈,這里是關(guān)鍵
  final List<ValueListenable<T>> valueListenables;

  final ValueListWidgetBuilder<T> builder;

  final Widget child;

  @override
  State<StatefulWidget> createState() => _ValueListenableListBuilderState<T>();
}

通過源碼可以知道,ValueListenable用來監(jiān)聽數(shù)據(jù)改變宏赘,從而刷新UI绒北,也就是我們常說的數(shù)據(jù)驅(qū)動UI。到這里察署,我們暫且思考下闷游,Mvvm+livedata+databinding是不是也是這個模式?其實基本一毛一樣了贴汪。

我隨便寫一個例子對比下,通過MutableLiveData綁定數(shù)據(jù)脐往,繼而在xml進行vm的綁定
xxviewModel.kt

  /**
     * 視頻地址觀察者
     */
    val videoUrl = MutableLiveData<String>(currentAlbum?.realPath)


 <com.example.widget.player.VideoPlayerView
            android:id="@+id/videoView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            binding:autoPlay="@{true}"
            binding:currentTimeTextView="@{current}"
            binding:layout_constraintBottom_toBottomOf="parent"
            binding:layout_constraintEnd_toEndOf="parent"
            binding:layout_constraintStart_toStartOf="parent"
            binding:layout_constraintTop_toTopOf="parent"
            binding:looping="@{true}"
            binding:playTag="@{viewModel.videoPlayTag}"
            binding:seekBar="@{progress}"
            binding:totalTimeTextView="@{total}"
            binding:videoUrl="@{viewModel.videoUrl}" />

等我寫完,放源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扳埂,一起剝皮案震驚了整個濱河市业簿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌阳懂,老刑警劉巖梅尤,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異岩调,居然都是意外死亡巷燥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門号枕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缰揪,“玉大人,你說我怎么就攤上這事葱淳《巯伲” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵蛙紫,是天一觀的道長拍屑。 經(jīng)常有香客問我,道長坑傅,這世上最難降的妖魔是什么僵驰? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上蒜茴,老公的妹妹穿的比我還像新娘星爪。我一直安慰自己,他們只是感情好粉私,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布顽腾。 她就那樣靜靜地躺著,像睡著了一般诺核。 火紅的嫁衣襯著肌膚如雪抄肖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天窖杀,我揣著相機與錄音漓摩,去河邊找鬼。 笑死入客,一個胖子當著我的面吹牛管毙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桌硫,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼夭咬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铆隘?” 一聲冷哼從身側(cè)響起卓舵,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎膀钠,沒想到半個月后边器,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡托修,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了恒界。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睦刃。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖十酣,靈堂內(nèi)的尸體忽然破棺而出涩拙,到底是詐尸還是另有隱情,我是刑警寧澤耸采,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布兴泥,位于F島的核電站,受9級特大地震影響虾宇,放射性物質(zhì)發(fā)生泄漏搓彻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旭贬。 院中可真熱鬧怔接,春花似錦、人聲如沸稀轨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奋刽。三九已至瓦侮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佣谐,已是汗流浹背肚吏。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留台谍,地道東北人须喂。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像趁蕊,于是被迫代替她去往敵國和親坞生。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

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

  • Flutter-Habit[https://github.com/lianyagang/flutter-habit...
    饅Care閱讀 1,360評論 5 9
  • 用兩張圖告訴你掷伙,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料是己? 從這篇文章中你...
    hw1212閱讀 12,699評論 2 59
  • 久違的晴天,家長會任柜。 家長大會開好到教室時卒废,離放學已經(jīng)沒多少時間了。班主任說已經(jīng)安排了三個家長分享經(jīng)驗宙地。 放學鈴聲...
    飄雪兒5閱讀 7,513評論 16 22
  • 今天感恩節(jié)哎摔认,感謝一直在我身邊的親朋好友。感恩相遇宅粥!感恩不離不棄参袱。 中午開了第一次的黨會,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,559評論 0 11
  • 在妖界我有個名頭叫胡百曉秽梅,無論是何事抹蚀,只要找到胡百曉即可有解決的辦法。因為是只狐貍大家以訛傳訛叫我“傾城百曉”企垦,...
    貓九0110閱讀 3,256評論 7 3