前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原来Flutter代码是这样运行在原生系统的!快来了解Flutter标准模板,感受原生系统中Flutter的魅力!

原来Flutter代码是这样运行在原生系统的!快来了解Flutter标准模板,感受原生系统中Flutter的魅力!

作者头像
JavaEdge
发布2023-07-09 16:04:40
4120
发布2023-07-09 16:04:40
举报
文章被收录于专栏:JavaEdge

通过Android Studio创建的Flutter应用模板,了解Flutter项目结构,分析Flutter工程与原生Android和iOS工程有哪些联系,体验一个有着基本功能的Flutter应用是如何运转的,从而加深你对构建Flutter应用的关键概念和技术的理解。

Dart只要理解基本编程概念(比如,类型、变量、函数和面向对象),并具备一定前端基础(了解View是什么、页面基本布局等基础),就可以和我一起完成计数器示例工程分析

Android Studio创建Flutter工程应用flutter_app。Flutter会根据自带的应用模板,自动生成简单计数器示例应用Demo。我们先运行此示例,效果如下:

每点击一次右下角带“+”号的悬浮按钮,就可以看到屏幕中央的数字随之+1。

1 工程结构

了解Flutter工程与原生Android和iOS工程关系及这些关系是如何确保Flutter程序最终运行在Android和iOS。

除Flutter本身的代码、资源、依赖和配置,Flutter工程包含Android和iOS工程目录。因为Flutter虽然是跨平台开发方案,但却需要一个容器最终运行到Android和iOS平台,所以 Flutter工程实际是同时内嵌Android和iOS原生子工程的父工程:在lib目录进行Flutter代码开发,某些特殊场景原生功能,则在对应Android和iOS工程提供相应代码实现,供对应Flutter代码引用。

Flutter会将相关依赖和构建产物注入这两个子工程,集成到各自项目。而我们开发Flutter代码,最终以原生工程形式运行。

2 工程代码

Flutter自带的应用模板,即计数器示例,对初学者是极好入门范例。从基础的组件、布局到手势的监听,再到状态的改变,Flutter最核心思想在这60余行代码。

为便学习理解,删掉核心流程无关组件配置代码及布局逻辑,不影响示例功能的情况下对代码进行改写,并分两部分:

  • 应用入口、应用结构以及页面结构,理解构建Flutter程序的基本结构和套路
  • 页面布局、交互逻辑及状态管理,理解Flutter页面是如何构建、如何响应交互,以及如何更新

3 第一部分代码,应用的整体结构

代码语言:javascript
复制
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(home: MyHomePage(title: 'Flutter Demo Home Page'));
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Widget build(BuildContext context) => {...};
}

Flutter应用为MyApp类的一个实例,MyApp类继承自StatelessWidget类,即应用本身也是一个Widget。Flutter中的Widget是整个视图描述的基础,Flutter中的包括应用、视图、视图控制器、布局等概念,都建立在Widget之上,Flutter核心设计思想是一切皆Widget。

3.1 Widget

组件视觉效果的封装,UI界面的载体,因此还要为它提供一个方法,告诉Flutter框架如何构建UI界面,即build。

3.1.1 build方法

通过对基础Widget进行相应UI配置或组合各类基础Widget进行UI定制化。如MyApp通过MaterialApp这个Flutter App框架设置应用首页,即MyHomePage。

3.2 MaterialApp类

是对构建material设计风格应用的组件封装框架,有很多可配置属性,如应用主题、应用名称、语言标识符、组件路由等,可参考Flutter官方的 API文档,了解MaterialApp框架的其他配置能力。

3.3 MyHomePage

应用首页,继承自StatefulWidget类,有状态Widget(Stateful Widget), _MyHomePageState就是其状态。

虽然MyHomePage类也是Widget,但与MyApp类不同,它没有build方法返回Widget,而是多个createState方法返回_MyHomePageState对象,而build方法包含在这 _MyHomePageState 类中。

3.4 StatefulWidget V.S StatelessWidget的接口设计

因为Widget要依据数据才能完成构建,对StatefulWidget来说,其依赖的数据在Widget生命周期中可能频繁变化。由State创建Widget,以数据驱动视图更新,而非直接操作UI更新视觉属性,代码表达更精炼,逻辑更清晰。

4 第二部分-页面布局及交互逻辑

代码语言:javascript
复制
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  void _incrementCounter() => setState(() {_counter++;});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(Widget.title)),
      body: Text('You have pushed the button this many times:$_counter')),
      floatingActionButton: FloatingActionButton(onPressed: _incrementCounter)
    );
  }

_MyHomePageState中创建的Widget Scaffold,是Material库提供的页面布局结构,包含:

  • AppBar,页面导航栏,直接将MyHomePage中的title属性作为标题使用
  • body,Text组件,显示了一个根据_counter属性可变的文本:‘You have pushed the button this many times:$_counter’。
  • floatingActionButton,页面右下角的“+”悬浮按钮。将 _incrementCounter 作为其点击处理函数

_incrementCounter

使用setState方法自增状态属性_counter。setState方法是Flutter以数据驱动视图更新的函数,会通知Flutter框架:我这儿有状态改变,赶紧给我刷新界面!而Flutter框架收到通知后,会执行Widget#build,根据新状态重建界面。

状态的更改一定要配合使用setState。通过该方法调用,Flutter会在底层标记Widget的状态,随后触发重建。示例即使修改_counter,若不调用setState,Flutter框架也不会感知到状态变化,因此界面也不会有任何改变。

图计数器示例的代码流程示意图,把这实例的整个代码流程串起:

MyApp为Flutter应用的运行实例,在main函数中调用runApp函数实现程序的入口。

应用首页则为MyHomePage,一个拥有_MyHomePageState状态的StatefulWidget。_MyHomePageState通过调用build方法以相应数据配置完成包括导航栏、文本及按钮的页面视图的创建。

而当按钮被点击之后,其关联的控件函数_incrementCounter会触发调用。在这个函数中,通过调用setState更新_counter属性同时,也通知Flutter框架其状态发生变化。随后,Flutter重新调用build方法以新数据配置重建_MyHomePageState的UI,最终完成页面重新渲染。

Widget只是视图的“配置信息”,是数据的映射,“只读”。对StatefulWidget,当数据改变时,需重建Widget去更新界面,即Widget创建销毁会很频繁。

为此,Flutter对此机制

5 优化

其框架内部会通过一个中间层收敛上层UI配置对底层真实渲染的改动,从而最大程度降低对真实渲染视图的修改,提高渲染效率,而不是上层UI配置变就要销毁整个渲染视图树重建。

这样Widget仅是一个轻量级的数据配置存储结构,它的重新创建速度非常快,所以我们可放心重建任何需更新的视图,无需分别修改各子Widget特定样式。

6 总结

先通过Flutter标准模板创建了计数器示例,并分析了Flutter的项目结构,以及Flutter工程与原生Android、iOS工程的联系,知道了Flutter代码是怎么运行在原生系统上的。

然后,学习示例项目代码,了解了Flutter应用结构及页面结构,并认识了构建Flutter的基础,也就是Widget,以及状态管理机制,知道了Flutter页面是如何构建的,StatelessWidget与StatefulWidget的区别,以及如何通过State的成员函数setState以数据驱动的方式更新状态,从而更新页面。

有原生Android和iOS框架开发经验的同学,可能更习惯命令式UI编程风格:手动创建UI组件,在需要更改UI时调用其方法修改视觉属性。而Flutter采用声明式UI设计,只需描述当前UI状态(即State),不同UI状态的视觉变更由Flutter在底层完成。

虽然命令式的UI编程风格更直观,但声明式UI编程方式好处是,可以让我们把复杂的视图操作细节交给框架去完成,这样一来不仅可以提高我们的效率,也可专注整个应用和页面的结构和功能。

7 FAQ

示例项目代码在_MyHomePageState类中,直接在build函数里以内联的方式完成了Scaffold页面元素的构建,这样做的好处是什么呢?在实现同样功能的情况下,如果将Scaffold页面元素的构建封装成一个新Widget类,我们该如何处理?

将Scaffold页面元素的构建封装成一个新Widget类的好处是可以提高代码的可复用性和可维护性。这样可以将Scaffold的构建逻辑封装到一个独立的组件中,方便在其他地方重复使用,也方便后续进行修改和维护。

如果要将Scaffold页面元素的构建封装成一个新Widget类,可以创建一个新的StatelessWidget或StatefulWidget类,然后在该类的build方法中返回Scaffold组件的代码。这样就可以在其他地方使用该组件来构建Scaffold页面元素。例如:

代码语言:javascript
复制
class MyScaffold extends StatelessWidget {
  final Widget body;

  const MyScaffold({Key? key, required this.body}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
      body: body,
    );
  }
}

然后在其他地方可以通过MyScaffold来构建页面元素,例如:

代码语言:javascript
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MyScaffold(
      body: Center(
        child: Text('Hello, World!'),
      ),
    );
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 工程结构
  • 2 工程代码
  • 3 第一部分代码,应用的整体结构
    • 3.1 Widget
      • 3.1.1 build方法
    • 3.2 MaterialApp类
      • 3.3 MyHomePage
        • 3.4 StatefulWidget V.S StatelessWidget的接口设计
        • 4 第二部分-页面布局及交互逻辑
          • _incrementCounter
          • 5 优化
          • 6 总结
          • 7 FAQ
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档