Flutter 学习笔记1【状态共享】 mobx

Flutter 中应用Mobx 实现全局状态共享

 

一.引入依赖

使用mobx, flutter_mobx, mobx_codegen, build_runner

pubspec.yaml

...
dependencies
mobx: ^1.2.1+4
flutter_mobx: ^1.1.0+2
...
dev_dependencies
build_runner: ^1.10.6
mobx_codegen: ^1.1.2

二.创建store文件

保存对应页面的状态

项目接口大致如下(按自己风格)

xxxproject/
lib/
...
store/
...
tabs.dart

三.编辑tabs.dart

tabs.dart

import 'package:mobx/mobx.dart';

/** 用于生成 tabsStore.g.dart **/
part 'tabsStore.g.dart';
class TabsStore = TabsStoreMobx with _$TabsStore;
/** 用于生成 tabsStore.g.dart **/

abstract class TabsStoreMobx with Store {
@observable
int bIndex = 0;
// TODO:数组类型的需要使用ObservableList类型, 目前没用到,暂时记录
@observable
ObservableList tabsList = ObservableList();
@action
void changeIndex(newIndex) {
bIndex = newIndex;
}
@computed
double get doubleTypeIndex => bIndex.toDouble();
}

// 单例使用tabsStore
TabsStore tabsStore = TabsStore();

四.生成*.g.dart文件

使用build_runner及mobx_codegen

在项目目录下使用终端执行指令:

首次
flutter packages pub run build_runner build
每次修改到这个存储store状态的文件后,都要删除*.g.dart文件,所以执行下面这个会方便一点
flutter packages pub run build_runner build --delete-conflicting-outputs
或者监听store目录的变化,自动生成
flutter packages pub run build_runner watch
此时的项目目录如下
xxxproject/
lib/
...
store/
...
tabs.dart
tabs.g.dart

五.正式使用mobx

我想实现一个tabbar功能, 使用BottomAppBar, 每个tabs按钮使用封装好组件作为子组件

父组件 Tabs.dart

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_salted_fish/components/BottomAppBarItem.dart';
import 'package:flutter_salted_fish/pages/tabs/AddAction.dart';
import 'package:flutter_salted_fish/pages/tabs/Home.dart';
import 'package:flutter_salted_fish/pages/tabs/Mine.dart';
import 'package:flutter_salted_fish/pages/tabs/Msg.dart';
import 'package:flutter_salted_fish/pages/tabs/PlayGood.dart';
import 'package:flutter_salted_fish/store/tabsStore.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class Tabs extends StatefulWidget {
 Tabs({Key key}) : super(key: key);

 @override
 _TabsState createState() => _TabsState();
}

class _TabsState extends State<Tabs> {
 
 // final tabsStore = TabsStore(); // 不能这样用

 // final Color _activeIconColor = Color.fromRGBO(255, 230, 15, 1);
 final Color _activeIconColor = Colors.amber;
 final Color _unselectedItemColor = Colors.grey;
 final Color _splashColor = Color.fromRGBO(255, 230, 15, 1);
 final List<Map> _bottomAppData = [
  {
     "label": "咸鱼",
     "icon": IconData(0xeee1, fontFamily: "AliIcons"),
     "index": 0,
  },
  {
     "label": "会玩",
     "icon": IconData(0xef31, fontFamily: "AliIcons"),
     "index": 1,
  },
  {
     "label": "添加",
     "icon": Icons.add,
     "index": 2,
  },
  {
     "label": "消息",
     "icon": IconData(0xeeda, fontFamily: "AliIcons"),
     "index": 3,
  },
  {
     "label": "我的",
     "icon": IconData(0xeee5, fontFamily: "AliIcons"),
     "index": 4,
  },
];
 List<Widget> _pageList = [
   Home(),
   PlayGoodPage(),
   AddAction(),
   MsgPage(),
   Mine()
];
 List<Widget> _generateBottomAppBarItem() {
   return this._bottomAppData.map((item) {
     return item["index"] == 2
         ? SizedBox()
        : BottomAppBarItem(
             iconData: item["icon"],
             label: item["label"],
             index: item["index"],
          );
  }).toList();
}

 @override
 void initState() {
   super.initState();
   setState(() {});
}

 @override
 Widget build(BuildContext context) {
   ScreenUtil.init(
     context,
     designSize: Size(750, 1334),
     allowFontScaling: false,
  );
   return Observer(
     builder: (_) => Scaffold(
       body: this._pageList[tabsStore.babIndex],
       bottomNavigationBar: BottomAppBar(
         notchMargin: ScreenUtil().setWidth(10.0),
         color: Colors.white,
         shape: CircularNotchedRectangle(), // 底部导航栏打一个圆形的洞
         child: Row(
           mainAxisAlignment: MainAxisAlignment.spaceAround, //均分底部导航栏横向空间
           children: this._generateBottomAppBarItem(),
        ),
      ),
       floatingActionButton: Stack(
         alignment: Alignment.bottomCenter,
         children: [
           FloatingActionButton(
             child: Icon(Icons.add, color: Colors.black, size: 24),
             foregroundColor: this._activeIconColor,
             backgroundColor: this._activeIconColor,
             focusColor: Colors.amber,
             hoverColor: Colors.amber,
             elevation: 0.0,
             focusElevation: 0,
             highlightElevation: 0,
             splashColor: this._splashColor,
             shape: RoundedRectangleBorder(
                 side: BorderSide(
                   width: 4,
                   color: this._activeIconColor,
                ),
                 borderRadius: BorderRadius.circular(30)),
             onPressed: () {
               tabsStore.changeIndex(2);
            },
          ),
        ],
      ),
       floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    ),
  );
}
}

子组件 BottomAppBarItem.dart

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_salted_fish/store/tabsStore.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class BottomAppBarItem extends StatefulWidget {
 var iconData = IconData(0xeee1, fontFamily: "AliIcons");
 String label = '咸鱼';
 int index = 0;
 BottomAppBarItem(
    {this.iconData,
     this.label,
     this.index,
     Key key})
    : super(key: key);

 @override
 _BottomAppBarItemState createState() => _BottomAppBarItemState();
}

class _BottomAppBarItemState extends State<BottomAppBarItem> {
 // final tabsStore = TabsStore(); // 不能这样用

 @override
 Widget build(BuildContext context) {
   return Container(
     child: InkWell(
       onTap: () {
         tabsStore.changeIndex(widget.index);
      },
       child: Container(
         width: ScreenUtil().setWidth(126),
         height: ScreenUtil().setHeight(90),
         child: Column(
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
             Icon(
               widget.iconData,
               color: tabsStore.babIndex == widget.index
                   ? Colors.amber
                  : Colors.grey,
            ),
             SizedBox(height: 4),
             Text(
               widget.label,
               style: TextStyle(
                 color: tabsStore.babIndex == widget.index
                     ? Colors.amber
                    : Colors.grey,
              ),
            ),
          ],
        ),
      ),
    ),
  );
}
}

 

如果在父子组件中都使用 TabsStore tstore = TabsStore(), 则父子组件实际上用的不是同一个实例的状态, 被这坑了一会

posted @ 2020-11-28 18:45  Jeecs  阅读(344)  评论(0)    收藏  举报