Flutter项目实现UI与逻辑分离

1,454 阅读2分钟

Flutter项目实现UI与逻辑分离

实际开发中随着开发的深入,功能会一点点的变多,如果UI代码与逻辑操作代码都写在一起,势必会造成一个文件的代码越来越多。这个时候就需要将一些逻辑代码抽离出来。

如何抽离

使用provider进行抽离。每个UI都会有一个provider去管理数据处理与一些用户的交换逻辑。
例如在实现一个"ETH钱包项目的欢迎页面"的时候。
功能有:1.创建新用户的入口, 2.根据钱包私钥导入用户,3根据keystore导入用户
实现方法:可以定义两个文件,一个是welcome_page.dart, 另一个是welcome_page_store.dart。然后利用provider将这两个文件关联起来。 (ps:需要引入 provider: 4.3.2 ) 例如下面的代码:
welcome_page.dart

import 'package:dimchat_app/business/tips/password_dialog.dart';
import 'package:dimchat_app/business/welcome/welcome_page_store.dart';
import 'package:dimchat_app/commom/utils/colours.dart';
import 'package:dimchat_app/commom/utils/dimens.dart';
import 'package:dimchat_app/commom/utils/image_utils.dart';
import 'package:dimchat_app/commom/utils/macros.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class WelcomePage extends StatefulWidget {
  @override
  _WelcomePageState createState() => _WelcomePageState();
}

class _WelcomePageState extends State<WelcomePage> {
  WelcomePageStore _welcomePageStore;

  @override
  void initState() {
    _welcomePageStore = WelcomePageStore(context: context);
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider.value(
        value: _welcomePageStore,
        child: Consumer<WelcomePageStore>(builder: (BuildContext context,
            WelcomePageStore welcomePageStore, Widget child) {
          return Scaffold(
            backgroundColor: Colors.white,
            body: Column(
              children: [
                Container(
                  width: Macros.screenWidthPX(),
                  child: Stack(
                    children: [
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          loadAssetImage("welcome/bg_top_left"),
                          Align(
                            alignment: Alignment.center,
                            child:  loadAssetImage('welcome/mid_icon'),
                          ),
                          Container(
                            margin: EdgeInsets.only(left: Dimens.gap_dp85),
                            child: loadAssetImage("welcome/bg_center"),
                          )
                        ],
                      ),
                      Positioned(right: 0, child: loadAssetImage("welcome/bg_right"),)
                    ],
                  ),
                ),
                GestureDetector(
                  onTap: () {
                    _welcomePageStore.createAccount();
                  },
                  child: Container(
                    height: Dimens.gap_dp50,
                    width: Dimens.gap_dp300,
                    padding: EdgeInsets.only(left: Dimens.gap_dp24, right: Dimens.gap_dp22),
                    margin: EdgeInsets.only(bottom: Dimens.gap_dp7, top: Dimens.gap_dp79),
                    decoration: BoxDecoration(
                      color: Colours.bg_btn_f4f4f4,
                      borderRadius: BorderRadius.all(Radius.circular(Dimens.gap_dp50/2))
                    ),
                    child: Stack(
                      children: [
                        Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text("创建身份", style: TextStyle(fontSize:Dimens.font_sp15, color: Colours.text_blue_2f97f3),),
                            Text("第一次使用钱包", style: TextStyle(fontSize:Dimens.font_sp10, color: Colours.text_gray_999999),)
                          ],
                        ),
                        Align(alignment: Alignment.centerRight, child: loadAssetImage("welcome/enter"))
                      ],
                    ),
                  ),
                ),
                GestureDetector(
                  onTap: () {
                    _welcomePageStore.importUser();
                  },
                  child: Container(
                    height: Dimens.gap_dp50,
                    width: Dimens.gap_dp300,
                    padding: EdgeInsets.only(left: Dimens.gap_dp24, right: Dimens.gap_dp22),
                    decoration: BoxDecoration(
                        color: Colours.bg_btn_f4f4f4,
                        borderRadius: BorderRadius.all(Radius.circular(Dimens.gap_dp50/2))
                    ),
                    child: Stack(
                      children: [
                        Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text("恢复身份", style: TextStyle(fontSize:Dimens.font_sp15, color: Colours.text_blue_2f97f3),),
                            Text("已拥有钱包", style: TextStyle(fontSize:Dimens.font_sp10, color: Colours.text_gray_999999),)
                          ],
                        ),
                        Align(alignment: Alignment.centerRight, child: loadAssetImage("welcome/enter"))
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );
        }));
  }
}

welcome_page_store.dart

import 'dart:convert';

import 'package:dimchat_app/business/welcome/import_user_page.dart';
import 'package:dimchat_app/commom/platform/dimchat_plugin/dimchat_platform.dart';
import 'package:dimchat_app/commom/utils/string_utils.dart';
import 'package:dimchat_app/commom/utils/toast.dart';
import 'package:dimchat_app/commom/utils/utils.dart';
import 'package:dimchat_app/model/dim_user_entity.dart';
import 'package:dimchat_app/model/version_entity.dart';
import 'package:flutter/cupertino.dart';
import 'package:dimchat_app/business/welcome/create_account_page.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../my_tabbar_page.dart';

class WelcomePageStore extends ChangeNotifier {
  BuildContext _context;

  String text;

  WelcomePageStore({BuildContext context}) {
    this._context = context;
  }

  getText() async {
    String ss = await DimchatPlatform.getChannel();
    VersionEntity versionEntity = VersionEntity().fromJson(json.decode(ss));
    text = versionEntity.version;
    notifyListeners();
  }

  createAccount() async{
    Navigator.push(_context, CupertinoPageRoute(
      builder:(context) {
        return CreateAccountPage();
      }
    ));
  }

  importUser() {
    Navigator.push(_context, CupertinoPageRoute(
        builder:(context) {
          return ImportUserPage();
        }
    ));
  }

  recoveryAccount(String psw) async {
    bool hasPermission = await Utils.checkPermission([Permission.storage]);
    if (!hasPermission) {
      hasPermission = await Permission.storage.request().isGranted;
    }
    if (!hasPermission) return;
    if (StringUtils.isNotEmpty(psw)) {
      DimUserEntity dimUserEntity = await DimchatPlatform.pswLogin(psw);
      if (null != dimUserEntity) {
        SharedPreferences sp = await SharedPreferences.getInstance();
        sp.setString("psw", psw);
        Navigator.pushAndRemoveUntil(_context, CupertinoPageRoute(
            settings: RouteSettings(name: "/MyTabbarPage"),
            builder:(context) {
              return MyTabbarPage();
            }
        ), (route) => route == null, );
      } else {
        Toast.show("恢复失败");
      }
    }
  }

}

解释一下代码
1.welcome_page_store.dart 文件: WelcomePageStore extends ChangeNotifier 需要继承ChangeNotifier

2.welcome_page.dart 文件:需要定义WelcomePageStore _welcomePageStore; 就好比句柄,welcome_page.dart的类手握着welcome_page_store.dart中的类。

3.welcome_page.dart的build方法里面需要使用ChangeNotifierProvider.value的方式去将两个文件关联起来。

 ChangeNotifierProvider.value(
        value: _welcomePageStore,
        child: Consumer<WelcomePageStore>(builder: (BuildContext context, WelcomePageStore welcomePageStore, Widget child) {

            }));

这样就可以把UI的代码放在welcome_page.dart 文件,一些页面跳转,导入数据的文本处理与一些用户数据的生成都可以放在welcome_page_store.dart 文件。 这样基本就做到了UI与逻辑分离。