Flutter框架 进阶一 Flutter-Habit 框架

Flutter-Habit诞生

Flutter-Habit
本文主要讲解,Flutter-Habit架构图解,全文架构,完全参照Android目前最流行的MVVM+DataBinding方式封装,目的旨在让客户端人员更加友好理解Flutter-Habit框架,进而能够进入快速开发

Flutter-基础功能拆解

  • base–提供基础组件,如缺省页,基础容器
  • constants–提供全局使用的常量、属性
  • helper–跨组件的全局属性
  • local–本地存储
  • network–网络管理,包括加解密
  • localizetion–多语言管理
  • utlis–工具类
  • widget–自定义控件
  • constant-config 配置文件
  • habit 插件交互管理
  • view_model 对外暴露
Flutter 核心功能讲解
  • BaseScaffold包括了几个核心的功能
    1.全局的ToolBar设置控制
  /// 设置ToolBar
  final Widget toolBar;

同时提供默认的ToolBar Widget

/// 获取当前的Toolbar的参数
  Widget _findCurrentToolBar() {
    /// 优先显示设置的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.生命周期的监听

///页面生命周期
enum PageState {
  RESUMED,
  INACTIVE,
  PAUSED,
  DETACHED,
}
声明页面的生命周期,进行相关业务开发

由于本文基于Android Mvvm+Databinding模式进行Flutter开发,所以,这里数据监听方式使用的是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();
                ///执行默认的返回按钮
                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);
  ///看这里,这里是关键
  final List<ValueListenable<T>> valueListenables;

  final ValueListWidgetBuilder<T> builder;

  final Widget child;

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

通过源码可以知道,ValueListenable用来监听数据改变,从而刷新UI,也就是我们常说的数据驱动UI。到这里,我们暂且思考下,Mvvm+livedata+databinding是不是也是这个模式?其实基本一毛一样了。

我随便写一个例子对比下,通过MutableLiveData绑定数据,继而在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}" />

等我写完,放源码

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

推荐阅读更多精彩内容

  • Flutter-Habit[https://github.com/lianyagang/flutter-habit...
    馒Care阅读 1,360评论 5 9
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,699评论 2 59
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,513评论 16 22
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,559评论 0 11
  • 在妖界我有个名头叫胡百晓,无论是何事,只要找到胡百晓即可有解决的办法。因为是只狐狸大家以讹传讹叫我“倾城百晓”,...
    猫九0110阅读 3,255评论 7 3