【Flutter开发】基于ChangeNotifier的MVVM架构实践

Flutter是谷歌出品,自然是天然适配MVVM架构,对于日常业务开发,使用该架构,可以很好地完成逻辑剥离,下面将实现一个demo讲解flutter中MVVM的实践。

一、跨组件状态管理框架:Provider

参考资料:https://book.flutterchina.club/chapter7/provider.html

 

二、架构模式图:

 

三、代码实现

  1. ViewModel层:ListDataViewModel.dart
    import 'package:flutter/cupertino.dart';
    import '../model/QueryListDataModel.dart';
    
    /**
     * 需要继承ChangeNotifier
     */
    class ListDataViewModel extends ChangeNotifier {
    
      ListDataViewModel(this.keyword);
      final String keyword;
    
      QueryListDataModel queryListDataModel;
      List<dynamic> listData = [];
    
      void getListDataFromNetwork() {
        //延时三秒返回结果,模拟网络请求
        Future.delayed(Duration(seconds: 3), () {
          queryListDataModel = QueryListDataModel();
          if (keyword.isNotEmpty) {
            listData.addAll(queryListDataModel.list);
            notifyListeners(); //通知监听者,必须要调用
          }
        });
      }
    }

     

  2. Model层:QueryListDataModel.dart
    class QueryListDataModel {
      List<String> list = [
        '测试数据1',
        '测试数据2',
        '测试数据3',
        '测试数据4',
        '测试数据5',
        '测试数据6',
        '测试数据7',
        '测试数据8',
        '测试数据9',
        '测试数据10',
        '测试数据11',
        '测试数据12',
        '测试数据13',
        '测试数据14',
        '测试数据15',
      ];
    }

     

  3. View层:ListPage.dart
    import 'package:flutter/material.dart';
    import 'package:flutter/widgets.dart';
    import 'package:my_app/viewmodel/ListDataHeadViewModel.dart';
    import 'package:my_app/viewmodel/ListDataViewModel.dart';
    import 'package:provider/provider.dart';
    
    class ListPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        /**
         * 使用ChangeNotifierProvider或者MutiProvider将需要共享数据的widget包起来,
         * 单个NotifierProvider使用ChangeNotifierProvider,
         * 多个NotifierProvider使用MutiProvider
         */
        return MultiProvider(providers: [
          ChangeNotifierProvider(
              create: (context) => ListDataViewModel('shanghai')),
          ChangeNotifierProvider(
              create: (context) => ListDataHeadViewModel())
        ],
          child: ListPageful(),
        );
      }
    }
    
    class ListPageful extends StatefulWidget {
      @override
      _ListPagefulState createState() => _ListPagefulState();
    }
    
    class _ListPagefulState extends State<ListPageful> {
    
      @override
      Widget build(BuildContext context) {
        /**
         * 可以在被包起来widget中的任一子widget中获取ViewModel,
         * 可以在在StatefulWidget中的build方法中获取,
         * 也可以使用Builder组件进行获取;
         */
        var listDataVM = Provider.of<ListDataViewModel>(context);
        return MediaQuery(
            data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
            child: ListPageImpl(listDataVM));
      }
    }
    
    class ListPageImpl extends StatefulWidget {
    
      ListDataViewModel listDataModel;
    
      ListPageImpl(this.listDataModel);
    
      @override
      _ListPageImplState createState() => _ListPageImplState();
    }
    
    class _ListPageImplState extends State<ListPageImpl> {
    
      ListDataViewModel listDataViewModel;
    
      List<dynamic> datas = [];
    
      @override
      void initState() {
        super.initState();
        /**
         * 在子widget中获取ViewModel,使用ViewModel获取数据,并对ViewModel添加监听,设置数据刷新界面;
         * (注:有两种方式刷新界面,<1>.监听数据,更改state的值刷新界面。<2>.直接在widget中使用ViewModel中的数据。具体根据业务需求;)
         */
        listDataViewModel = widget.listDataModel;
    
        listDataViewModel.getListDataFromNetwork();
        listDataViewModel.addListener(() {
          if (mounted) {
            this.setState(() {
              datas = listDataViewModel.listData;
            });
          }
        });
      }
    
      @override
      void dispose() {
        /**
         * 在界面销毁时移除对ViewModel的监听
         */
        listDataViewModel.removeListener(() {});
      }
    
      @override
      Widget build(BuildContext context) {
    
        return Scaffold(
          appBar: AppBar(
            title: Text('MVVM Demo'),
          ),
          body: ListView.builder(
              padding: EdgeInsets.all(16.0),
              itemCount: datas.length,
              itemBuilder: (context, i) {
                if (i.isOdd) {
                  return Divider();
                }
                return _buildRow(datas.length != 0? datas?.elementAt(i):"");
              }),
        );
      }
    
      Widget _buildRow(dynamic model) {
        return ListTile(
          title: Text(
            model,
            style: TextStyle(fontSize: 24.0, color: Color(0xFFFC6E51)),
          ),
        );
      }
    }
    
    
    


    相关说明已经在代码注释中体现。

 

demo源码已上传github:https://github.com/hanren726/FlutterMVVM_Demo,欢迎star和folk~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值