美文网首页flutter
基于GetX 搭建通用flutter 项目《五》(基于GetX

基于GetX 搭建通用flutter 项目《五》(基于GetX

作者: 火之夜工作室 | 来源:发表于2022-08-02 11:13 被阅读0次

    基于GetX 搭建通用flutter 项目《一》

    基于GetX 搭建通用flutter 项目《二》(界面规范抽象类)

    基于GetX 搭建通用flutter 项目《三》(暗黑模式)

    基于GetX 搭建通用flutter 项目《四》(国际化)

    最后还是到了这一步,经过 基于GetX 搭建通用flutter 项目《一》基于GetX 搭建通用flutter 项目《二》(界面规范抽象类)这两篇文章的讲解。
    大家应该都会纳闷,不是说好的GetX吗?,我也就在基于GetX 搭建通用flutter 项目《三》(暗黑模式)这里看到出现过和使用过,其他的毛都没有。
    你是不是不想分享啊,NONONO,少侠莫急,我只是想先把动态刷新所依赖的抽象类讲解一下,其实项目里用的GetX抽象类,也是基于第二篇的抽象类,对项目进行了定制化的扩展,如果看过项目代码的人,应该理解了我的思路,其实就是抽象类纯粹点,组合方式多一点 好,还是老规矩,上“技师”.

    • DEMO更新日志

      2022-07-14 完成国际化
      2022-06-22 完成暗黑模式功能开发
      2022-06-16 完成项目基础架构
      

    您能在这里看到啥

    1. GetView抽象类
    2. GetList抽象类
    3. GetController抽象类
    4. 使用例子

    GetView抽象类

    // ignore: must_be_immutable
    
    abstract class NormaGetxView<T extends NormalGetxController> extends GetView<T>
    with AbstractAttribute, AbstractWidget {
        NormaGetxView({Key? key}) : super(key: key);
        @override
        PageState get pageState => controller.pageState.value;
        @override
        Widget build(BuildContext context) {
            return createScaffol(
            context: context,
            safeAreatop: safeAreatop,
            safeAreabottm: safeAreabottm,
            pageState: pageState,
            title: title,
            backgroundColor: backgroundColor,
            navbackcolor: navbackcolor,
            resizeToAvoidBottomInset: resizeToAvoidBottomInset);
        }
    
    
        /// 抽离通用colum 方法,用layoutbuilder包裹的目的
        /// 为了解决web 开发时,设置最大布局
        /// 分为 createObxWidget() 和 createObxColumWidget()
        @override
        Widget createColumWidget(BuildContext context) {
            return Container(
                alignment: Alignment.center,
                child: LayoutBuilder(
                    builder: (context, constraints) {
                        /// 这个方法是为了设置界面在web端的时候,
                        /// 也能让界面拉伸的情况正常显示的宽度最大值
                        /// 不过一般不适配web的话,没必要这样写
                        /// 也可以不用LayoutBuilder包裹,看你使用情况吧
                        configlayoutbuiderConstraints(constraints);
                        return Container(
                            alignment: Alignment.centerLeft,
                            width: configSizeBoxWidth(constraints),
                            child: createObxWidget(),
                        );
                    },
                ),
            );
        }
    
        /// 为 getx 新增包裹方法
        /// 我这里使用Obx把整个界面包裹着,
        /// 为了更好的刷新
        Widget createObxWidget() {
            return Obx(
                () => createObxColumWidget(),
            );
        }
        
        /// getx 真实包裹的colum 方法
        /// 这个就和我们通用抽象类的方法差不多
        /// 我这里还是把它分成了
        /// header + body
        Widget createObxColumWidget() {
            return Column(
                children: [
                    createHeaderWidget(),
                    Expanded(
                        child: createBody(Get.context!),
                    ),
                 ],
           );
        }
    
        /// 获取 屏幕 最大尺寸
        configlayoutbuiderConstraints(BoxConstraints constraints) {
            controller.configsiezw(configSizeBoxWidth(constraints));
        }
        double configSizeBoxWidth(BoxConstraints constraints) {
            return HzyNormalUtils.configSizeMaxW(constraints.maxWidth);
        }
    
    }
    

    这样我们的GetView 的抽象类就做好了,是不是很简单,下面我们来看一下,细心的小伙伴,肯定也发现了个东东.
    那就是我们抽象类的NormalGetxController通用控制器.不过不要心急,我会在下面讲解一下的.
    好了我们来看一下GetListView抽象类

    GetList抽象类

    由于是列表页,这里我们需要上下啦刷新控件,我这里使用的是flutter_easyrefresh这个刷新控件.下面我们就看一下我是怎么使用的,当然由于我们使用的Get,我也把界面和逻辑完全抽离了.先讲一下界面

    // ignore: must_be_immutable
    abstract class NormalGetxListView<T extends NormalGetxListController>
    extends NormaGetxView<T> with AbstracRefreshWidget {
        NormalGetxListView({Key? key}) : super(key: key);
        
        @override
        Widget createBody(BuildContext context) {
            return createRefreshWidget(context);
        }
        
        /// 创建列表刷新控件
        @override
        Widget createRefreshWidget(BuildContext context) {
            return EasyRefresh(
                key: key,
                /// 这里边把控制器的创建也交给了Controller
                controller: controller.refreshController ?? EasyRefreshController(),
                onRefresh: () async {
                    /// 下啦刷新触发方法也是交给了控制器
                    controller.configRefresh();
                },
                onLoad: () async {
                    /// 同样的上啦加载也是交给了控制器
                    controller.configLoading();
                },
                child: createListView(context),
                header: createHeader(),
                footer: createFooter(),
                emptyWidget: createEmptyWidget(),
            );
        }
        
        /// 这里算是新增了自定义刷新header的方法
        /// 都是为了使用者可以完全的自定义
        Header? createHeader() {
            return ClassicalHeader(、
                refreshingText: '正在刷新...',
                refreshedText: '刷新成功',
                refreshReadyText: '松开刷新',
                refreshFailedText: '刷新失败',
                refreshText: '下拉刷新',
                showInfo: false,
                textColor: CommentColorS.col000000,
            );
        }
        /// 这里算是新增了自定义刷新footer的方法
        Footer? createFooter() {
            return ClassicalFooter(
                loadText: "上啦加载更多数据",
                loadReadyText: "松开加载",
                loadingText: "正在加载...",
                loadedText: "加载成功",
                loadFailedText: "加载失败",
                noMoreText: "没有更多数据了~",
                showInfo: false,
                textColor: CommentColorS.col000000,
            );
        }
    }
    
    

    我们也是引用了我们之前AbstracRefreshWidget列表抽象类,这样就减少了,我们重复的写,只需要重写需要自定义的方法即可.我们这边总共重写2个方法,来实现GetList的抽象类,具体就不多少了,代码上都有讲解.

    GetController抽象类

    这里面我就直接controllerlistcontroller 一起来讲解了,因为listcontroller也是继承了controller,看代码

    abstract class NormalGetxController extends GetxController {
        /// 界面状态值,用于刷新界面 显示效果
        var pageState = PageState.initializedState.obs;
          
        /// 配置点击失败界面 刷线方法
        /// 这个是当失败界面点击刷新的预留触发方法,
        /// 子类可以重写这个方法 来实现数据刷新
        configreload(){}
    
    }
    
    
    abstract class NormalGetxListController extends NormalGetxController
    
    implements AbstractNetWork {
        /// 刷新控制器
        EasyRefreshController? refreshController;
        /// 页数
        int page = 1;
        @override
        void onInit() {
            super.onInit();
            refreshController = EasyRefreshController();
        }
    
        // 下啦刷新触发事件
        configRefresh() async {
            page = 1;
            getnetworkdata(1, configNetWorkParmas());
    
        }
    
        // 上啦加载更多触发事件
        configLoading() async {
            page++;
            getnetworkdata(2, configNetWorkParmas());
    
        }
    
        /// 网络请求 参数方法
        @override
        Map<String, dynamic>? configNetWorkParmas() {
            return null;
        }
    
        /// 网络请求数据
        @override
        void getnetworkdata(int? type, Map<String, dynamic>? info) async {}
        
        
        /// 结束刷新方法
        /// type == 1 代表下拉刷新
        /// tyep == 2 代表上啦加载
        void endRefresh({int? type, PageState? state}) {
            bool success = true;
            bool noMore = false;
            /// 根据状态值 配置是否有更多数据
            if (state == PageState.noMoreDataState) {
                noMore = true;
            }
            /// 根据状态值,判断数据是否请求成功
            if (state == PageState.errorState ||
            state == PageState.erroronlyTotal ||
            state == PageState.errorshowRelesh) {
                success = false;
            }
    
            if (refreshController != null) {
                if (type == 1) {
                    refreshController!.finishRefresh(success: success);
                    refreshController!.resetLoadState();
                } else if (type == 2) {
                    /// 在这里 配置上啦加载 是否有更多数据
                    refreshController!.finishLoad(success: success, noMore: noMore);
                }
             }
             pageState.value = state!;
        }
    
    

    从控制器看到,我们在界面里所需要做的上下啦刷新事件,以及网络请求,业务逻辑,都会在这里完成,这样view 只关心显示问题就行,所有的状态都是通过控制器来控制的.

    到此,这个抽象类算是封装完成,下面看看到真的项目中应该怎么使用呢

    使用例子

    相对来说,由于上面的抽象类是通用型的,我一般会在新的项目里,以上面的为基准,会在封装一个适合当前项目的抽象类.这里我就只讲一下适用本项目的控制器抽象类,然后再讲一下界面使用

    本项目控制器抽象类
    abstract class CommonGetXController extends NormalGetxController {
        /// 项目中 使用的失败界面的标识,用于使用者 显示不同的界面
        /// 具体 使用,一般是通过网络请求,进行逻辑处理
        var placeHoldType = CommonPlaceHoldType.nonetwork;
    
    }
    
    abstract class CommonGetXListController extends NormalGetxListController {
        /// 项目中 使用的失败界面的标识,用于使用者 显示不同的界面
        /// 具体 使用,一般是通过网络请求,进行逻辑处理
        var placeHoldType = CommonPlaceHoldType.nonetwork;
       
        /// 这个就是上面 失败出发方法,
        /// 我这里就简单的用了,方法是触发登录,还是触发列表下啦刷新
        /// 两个事件,这个可根据你们自己业务进行扩展
        @override
        configreload() {
            if (UserStateController.isLogin) {
                refreshController?.callRefresh();
            } else {
                currentToPage(LoginPageId.login);
            }
        }
    }
    
    
    列表事例

    请看项目中的 home_list_v.dart 和 home_list_c.dart 这两个dart类的实现,由于代码多,就不在这显示.

    到此,基本上想分享的都讲完了,如果不理解可以在下面评论,或者多看看项目代码.喜欢的可以点点赞,你们的鼓励,就是我前进的东西.谢谢

    hzy_normal_widget 是我在使用GetX搭建项目时,总结的一些通用开发控件,方便我们在开发的时候,减少重复性界面代码的创建.

    ttcomment 通用项目的界面接口基类,和一些通用工具类,喜欢的可以点点star.

    当然接下的时间里我也会总结OCswift 相应的通用项目文章,喜欢的可以点点关注

    相关文章

      网友评论

        本文标题:基于GetX 搭建通用flutter 项目《五》(基于GetX

        本文链接:https://www.haomeiwen.com/subject/dierwrtx.html