Flutter的开发规范

一、页面Page规范前后效果对比

我们先从页面开始(以登录页的优化为例),然后逐步的从点到面铺开描述。

目标:页面布局、控件定义、事件处理分离。

1、演示的Page的UI图

用户名登录的UI图

2、规范前的效果

规范前:未进行任何处理的时候,你的代码是这样的。

LoginPage_widgetUnsplit.jpg

3、规范后的效果

规范后**:按规范处理后你代码的效果是这样的,

LoginPage_widgetSplit.jpg

可见通过处理后Page的整体代码更加简洁了。

二、页面Page开发规范的细则

1、规范一:将每个Widget的定义整理到单独的函数里

写:

Flutter规范_Widget_right.jpg

不写:

Flutter规范_Widget_wrong.jpg

2、规范二:将各个Widget组成界面的布局放到widgets()方法里处理

写法如下:

Flutter规范_Widgets布局_right.jpg

如此通过以上两步后,Widget build中的代码即会变为如下:

Flutter规范_WidgetBuild_right.jpg

如此通过以上几个拆分,我们的Page页面就显得很简洁和很好维护了。

3、规范三、Widget的封装

细心的你,可能发现了我们这里有一个系统没有的LoginTextField文本框类。是的,该类是我们自定义封装到Package后来使用的。

对于一个控件怎么封装,详情查看之前的文章《Flutter进阶(2):控件Widget的自定义与封装》

三、页面Page规范小结

  • 1、Widget build方法

build方法里尽量用最少的代码实现整体视图。如下,我们将登录页中的所有Widget通过loginWidgets()函数封装起来。

  • 2、各个Widget组成的视图布局

loginWidgets()方法里实现页面Widgets的布局。而对于Widget的定义为了不让页面布局控件定义因写在一堆,而造成代码一大坨。我们对每个Widget单独提供定义的函数,如userNameTextField()即为定义用户文本框的函数。

  • 3、抽离每个Widget的定义

  • 4、封装单个Widget

四、业务逻辑的开发规范

说完了页面上的Widgets的开发规范,下面就轮到页面上的业务逻辑的开发规范了。

拿登录页需要获取上次登录的账号来说,它的业务是getDefaultLoginAccountAction,下面以混编时候的项目为例

1、未去解耦业务时候的登录页

getDefaultLoginAccountAction在Page中的实现一般为:

/// LoginPage.dart 中的业务代码
  static const callNativeMethodChannel = const MethodChannel('com.dvlproad.ciyouzen/callNativeLoginMethodChannel');
  Future _getDefaultLoginAccountAction() async {
    try {
      final Map nativeResponse = await callNativeMethodChannel.invokeMethod('getDefaultLoginAccountAction');
      final Map nativeResult = callNativeNativeResult(nativeResponse);

      setState(() {
        userName = nativeResult["userName"];
        password = nativeResult["password"];
        print(userName + ":" + password);
        _usernameController.text = userName;
        _passwordController.text = password;
      });
    } on PlatformException {}
  }

相应的它的调用为:

/// LoginPage.dart 未去解耦时候的登录页
class MyLoginPage extends StatefulWidget {
  MyLoginPage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyLoginPageState extends State {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("Login Page initState");

    _getDefaultLoginAccountAction();
  }
  
  // other things
}

可见上述的业务处理getDefaultLoginAccountAction中,掺杂了对页面Page的setState操作,这不适合我们以后只对业务或者只对页面做修改的处理。所以下面我们将它们解耦。

2、解耦业务时候的登录页

[图片上传失败...(image-1a7cf4-1552384194828)]

getDefaultLoginAccountAction在ChannelModel中的实现一般为:

/// LoginChannelModel.dart 文件
Future> getDefaultLoginAccountAction() async {
  try {
    final Map nativeResponse = await callNativeMethodChannel.invokeMethod('getDefaultLoginAccountAction');
    final Map nativeResult = callNativeNativeResult(nativeResponse);

    return nativeResult;
  } on PlatformException {
    return null;
  }
}

相应的它的调用为:

/// LoginPage.dart 解耦时候的登录页
class MyLoginPage extends StatefulWidget {
  MyLoginPage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyLoginPageState extends State {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("Login Page initState");

    getDefaultLoginAccountAction().then((nativeResult){
      setState(() {
        userName = nativeResult["userName"];
        password = nativeResult["password"];
        print(userName + ":" + password);
        _usernameController.text = userName;
        _passwordController.text = password;
      });
    });
  }
  
  // other things
}

五、Flutter Channel的数据规范

在使用Flutter与原生项目混编的时候,因为涉及到数据传输,所以我们有必要在前期就对传输数据的进行规范统一。
此步略。

结束语

时间仓促,后续会再完善。

你可能感兴趣的:(Flutter的开发规范)