跨平台技术性能分析

217 阅读7分钟

Flutter技术讨论

简单回顾下跨平台技术的发展趋势

blog.51cto.com/u_15294985/…

跨平台技术关注的几个因素

如何提高研发效率,产品快速迭代、快速试错成为非常重要的因素。

多端的功能完全一样,却需要各自开发一遍

提单一端高开发效率

i. 编译时间长

ii. 目标界面有时候会很深,我们修改哪怕很少的几行代码都得重新构建,安装,运行

iii. 现场还原麻烦

关注研发效率的同时能否做出一个性能比较高的应用

因性能造成的延迟等问题会随时导致用户和订单的流失

对性能的追求是无止境的

多端一致性问题

我的理解主要是UI的一致性问题

        比如设计师按照ios的组件设计UI,Android实现起来比较麻烦

        长时间的积累,有时候会导致在同期版本中不同客户端功能一致

        给项目的维护和QA测试都造成一些麻烦

动态化问题

在移动开发中,动态化技术极其重要

让APP保持最新的版本

让业务开发变得更加快捷

动态修复线上bug

动态化技术主要包含4种,补丁、插件化、Web和混合方案。

跨端技术在这几年的发展历程

Ionic metero xamarin electron WASM 等

跨端技术类型

跨端技术分为几类:

• WebView:通过调 WebView 的技术去渲染,我们的小程序也是基于这一块。

• 原生渲染:通过各种技术调中间层转换,最终渲染,安卓还是调安卓的,iOS 的还是调 iOS 的。

• 自渲染:可以不借助系统的,自己写一套自渲染技术

不管跨端技术怎么演变,主要就是分这三大类。

Flutter 技术优势

Flutter 的高效率

a. 一次开发,双端部署

b. Hot reload, Hot restart

(Android 中的 Instant Run 使用限制大,开发中几乎很少用 blog.csdn.net/jb_home/art…

c. 响应式设计模式

Android MVVM

        Android Compose

        响应式设计模式(讨论)

             状态管理 2.3 状态管理 | 《Flutter实战·第二版》

响应式的编程框架中都会有一个永恒的主题——“状态(State)管理”,无论是在 React/Vue(两者都是支持响应式编程的 Web 开发框架)还是 Flutter 中,他们讨论的问题和解决的思想都是一致的。

             数据和渲染方法分离是前提条件

Flutter 的高一致性

在MD-App开发过程中,几乎没有双端不一致的情况

现在的 QA 基本只拿Android测试,然后在最终版本在IOS上过一遍,几乎很少有问题

当然,这种测试方式还有待商榷,因为还有许多需要特别注意地方,比如一些有平台差异的功能点的问题,像权限的申请,文件的保存等等

Flutter 的高性能

Flutter 的动态化

对于Flutter来讲,官方并不支持动态化

第三方动态化方案感觉还不是很成熟,并且方案大部分都是往js的等方向再走,感觉不是很好

所以感觉暂时还不是考虑Flutter的动态化特性的时候

在MD-App应用中的使用情况

开发效率,性能,高一致性,生态

Flutter UI 的三棵树

从创建到渲染的大体流程是: 根据Widget生成Element,然后创建相应的RenderObject并关联到Element.renderObject属性上,最后再通过RenderObject来完成布局排列和绘制。

Widget

轻量级的UI描述信息/配置信息/界面信息的元数据

不负责任何的实际布局,UI的配置信息封装在这里

每次build的时候创建新的

所以我的理解是 Widget 更像是 Element 的生成器和或者更新器

Element

控制Widget的生命周期

保存一些状态,保存renderObject

RenderObject

最终真实的去做布局渲染数据处理的

StatelessWidget VS StatefulWidget

Flutter 中是通过 Widget 嵌套 Widget 的方式来构建UI和进行实践处理的,所以,Flutter 中万物皆为Widget。

在Flutter中,widget分为两类:Stateful(有状态)和 stateless(无状态)widget。

stateless widget

没有内部状态,Icon、IconButton, 和Text都是无状态widget, 它们都是 StatelessWidget的子类。

stateful widget 是动态的,用户可以和其交互(例如输入一个表单、 或者移动一个slider滑块),或者可以随时间改变 (也许是数据改变导致的UI更新)。Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 它们都是 StatefulWidget的子类。

StatefulWidget

book.flutterchina.club/chapter2/fl…

Stateful widgets 持有的状态可能在widget生命周期中发生变化。

创建一个StatefulWidget

1. 要创建一个自定义有状态widget,需创建两个类:StatefulWidget和State。

2. 我们要定义一个widget类,继承自StatefulWidget。

3. 子State,包含该widget状态并定义该widget build()方法的类,它继承自State。

4. 状态对象包含widget的状态和build() 方法。

5. 当widget的状态改变时,状态对象调用setState(),告诉框架重绘widget

StatefulWidget (state) 的生命周期

image.png


import 'package:flutter/material.dart';

///这是一个用StatefulWidget展示Flutter页面生命周期的类

/*
 * StatelessWidget 只有createElement()和build()两个生命周期函数
 * StatefulWidget生命周期分三种状态
 * 1.初始化时期
 *   createState();initState();
 * 2.更新时期
 *   didChangeDependencies();build();didUpdateWidget()
 * 3.销毁时期
 *   deactivate();dispose();
 */
class WidgetLifecycle extends StatefulWidget {

  const WidgetLifecycle({Key? key}) : super(key: key);

  @override
  ///createState()是初始化期的生命周期函数;
  ///创建 StatefulWidget 之后调用的第一个方法 ;
  ///且createState()是每一个StatefulWidget必须重写的方法
  _WidgetLifecycleState my_createState(){
    print("这里是createState()函数");
    return new _WidgetLifecycleState();
  }
  _WidgetLifecycleState createState() => my_createState();
}

class _WidgetLifecycleState extends State<WidgetLifecycle> {
  int _cout = 0;
  ///initState()是创建Widget时调用的构造方法后第一个方法,
  ///执行顺序在createState()之后
  ///类似于Android中的onCreate()/IOS中的viewDidLoad()
  ///通常这个方法用于做初始化的工作,如channel的初始化,监听器的初始化
  @override
  void initState() {
    print("这里是initSate()函数");
    super.initState();
  }

  ///1.didChangeDependencies()在初次构建Widget后,继initState()后立即调用
  ///2.如果StatefulWidget依赖InheritedWidget,那么当前State所依赖的InheritedWidget
  ///中的变量改变时,会被再次调用
  ///InheritedWidget是一个Widget,用于Widget树中高效向下传递,共享数据
  @override
  void didChangeDependencies() {
    print("这里是didChangeDependencies()函数");
    super.didChangeDependencies();
  }

  ///build()是一个一定会被调用的方法,用于实现要呈现的页面内容
  ///执行顺序在didChangeDependencies()函数之后立即调用,
  ///或在setState()函数被调用后
  @override
  Widget build(BuildContext context) {
    print("这里是build()函数");
    return Scaffold(
      appBar: AppBar(
        title: Text("Widget生命周期/页面生命周期"),
        leading: BackButton(),
      ),

      ///Center()是一个约束组件
      body: Center(
        child: Column(
          children: <Widget>[
            ElevatedButton(
              onPressed: (){
                setState(() {
                  _cout++;
                });
              },
              child: Text("点我",
                style: TextStyle(fontSize: 26),),
            ),
            Text(_cout.toString()),
          ],
        ),
      ),
    );
  }

  ///非常用的更新生命周期方法
  ///当父组件被重绘时被调用
  ///didUpdateWidget()携带一个旧组件参数,可以用于与新组件进行对比
  @override
  void didUpdateWidget(covariant WidgetLifecycle oldWidget) {
    print("这里是didUpdateWidget()函数");
    super.didUpdateWidget(oldWidget);
  }

  ///deactivate() 不常用的销毁生命周期方法
  ///组件被移除时候被调用,且在dispose()前进行调用
  @override
  void deactivate() {
    print("这里是deactivate()函数");
    super.deactivate();
  }

  ///dispose() 常用的销毁生命周期方法
  ///用于组件被销毁时候调用
  ///通常资源的释放,监听器的卸载,channel的销毁会在这里执行
  @override
  void dispose() {
    print("这里是deactivate()函数");
    super.dispose();
  }
}

Flutter的布局原理(docs.flutter.dev/development…)

译文(blog.csdn.net/flutterdevs…

刚接触Flutter常遇到的一个问题

image.png

约束,尺寸,位置

约束向下,尺寸向上,Parent决定位置

类似于Android的布局原理

Widget 是树形结构

image.png

1. 上层组件向下层组件传递约束(constraints)条件。 Android(measure spec)

2. 下层组件确定自己的大小,然后告诉上层组件。注意下层组件的大小必须符合父组件的约束。(android:setSize)

3. 上层组件确定下层组件相对于自身的偏移和确定自身的大小(大多数情况下会根据子组件的大小来确定自身的大小)。(layout)

约束的种类

Terminology

1. When the minimum constraints and the maximum constraint in an axis are the same, that axis is tightly constrained. See: new BoxConstraints.tightFor, new BoxConstraints.tightForFinite, tighten, hasTightWidth, hasTightHeight, isTight.

2. An axis with a minimum constraint of 0.0 is loose (regardless of the maximum constraint; if it is also 0.0, then the axis is simultaneously tight and loose!). See: new BoxConstraints.loose, loosen.

3. An axis whose maximum constraint is not infinite is bounded. See: hasBoundedWidth, hasBoundedHeight.

4. An axis whose maximum constraint is infinite is unbounded. An axis is expanding if it is tightly infinite (its minimum and maximum constraints are both infinite). See: new BoxConstraints.expand.

5. An axis whose minimum constraint is infinite is just said to be infinite (since by definition the maximum constraint must also be infinite in that case). See: hasInfiniteWidth, hasInfiniteHeight.

6. A size is constrained when it satisfies a BoxConstraints description. See: constrain, constrainWidth, constrainHeight, constrainDimensions, constrainSizeAndAttemptToPreserveAspectRatio, isSatisfiedBy.

image.png

理解了Flutter的布局原理,或许在看文档的过程中会事半功倍

学习资料

1.  Flutter中文网  flutterchina.club/

2. 王叔不秃 space.bilibili.com/589533168/?…

3. awesome-flutter github.com/Solido/awes…

4. Flutter In Action

5. github.com/toly1994328…

讨论

Fastlane 构建工具