Flutter 第一个程序Hello World!

简介: Flutter 第一个程序Hello World!

前言


 Flutter实际上在我学习Android之前就已经听说过了,不过那时候的Flutter还是初始版本,并不如原生,虽说有跨平台的优势,但也只是了解而已,没有去正式使用,那么为什么又要学习了呢?


正文


 因为时代又进了一步,现在流行内卷,你不卷别人,别人就要卷你。没办法!以往学习Flutter的大多数是前端转的,而现在大部分都是熟悉Android或者IOS的开发工程师在公司预算不足以招满两个端的前景下,去学习Flutter,怎么说呢?行走江湖,技多不压身,你可以不用精通,但你得会,不说别的,起码能让你在简历的技能栏上多写上一行,何乐而不为呢?


 下面我们开始接触Flutter,首先你需要知道Flutter的官网地址:Flutter官网,Flutter中文官网,在学习过程中很多资料你都可以通过官网去查询,你所遇到的任何问题都能解决,只不过刚开始对你来说你需要走很多的弯路。


 Flutter开发使用的是Dart语言,不用害怕,实际上并不难。目前最新的Flutter版本是3.x.x,在我刚听说Flutter的时候还是1.0版本,那个时候使用起来其实效果不是很好,缺少很多的依赖支持库,而且和原生的差距比较大,而在2.0的时候Flutter就已经有很大的优化了,这时候开发者和开源项目如雨后春笋一般猛增,而现在已经到了3.0,很多公司会直接在招人要求上写Flutter技能,为什么想必就不用我多说了。


一、Flutter SDK下载


 Flutter作为跨平台的技术,可以在Windows、macOS、Linux、Chrome OS上安装,我这里使用的是Windows11,等我有钱了,我高低弄一个macOS,到时候Android Studio XCode都能配置起来。 下面先下载Flutter SD,地址:Flutter SDK,在里面可以看到最新的SDK版本。

800ef8d826f94989b0ecc2d7ba9d7ac0.png


 我这里看到最新的是3.0.5,这个版本更新的还是很频繁的,点击这个3.0.5就会弹窗下载。

3488251406774aa69c22ecbcfe51f4f7.png


 还挺大的,下载好之后,解压到指定的路径下,最好不要放在C盘,即使放在C盘也不要放在高级权限的路径中,比如User下。而我就直接解压在D盘中,如下图所示:

c9d92cfa77774679b261efa657008ca1.png


默认的文件夹是flutter,我这里改成了Flutter,看个人习惯。


二、环境变量配置


 右键点击计算机图标,依次选择属性 → 高级系统设置 → 高级 → 环境变量。

ab280689fd1a489b9279e00202031123.png


 环境变量有两种,一种是用户变量,一种是系统变量,我们只需要配置用户变量。点击新建按钮,输入变量名和变量值。

变量名:PUB_HOSTED_URL
变量值:https://pub.flutter-io.cn


4862608daead4c039cf74e9f9c249958.png


输入完成之后点击确定,这个变量就保存了。


还有一个变量,继续点击新建。

变量名:FLUTTER_STORAGE_BASE_URL
变量值:https://storage.flutter-io.cn


如下图所示操作。

85c34a9099634b31a9debe9fc43680cd.png


 上面这里的用户环境变量配置是镜像配置,Flutter 源站在国内可能不太稳定,因此谷歌中国开发者社区(GDG)专门搭建了临时镜像,使得我们的 Flutter 命令行工具可以到该镜像站点下载所需资源。


 最后我们配置SDK的路径

d15490c5aef34d9a9782b22ae2dbfc20.png


 选中用户变量的Path,点击编辑,会弹出一个窗口,先不管它。我们进入到刚才的Flutter目录下的bin文件中。

58a0cd30d85a4814a09d4c1f5b089b22.png


 需要将这个文件夹路径复制一下:也就是 D:\Flutter\bin,回到之前的那个窗口。

919168cb4bac4a9d8ff7d6e58b4d8852.png


 点击新建,粘贴刚才SDK路径,点击确定。然后关闭掉当前的所有窗口,重启你的电脑,记得加一个收藏,这样你重启电脑之后还能找到这篇文章,重启电脑后进入第三步。


三、Android Studio 开发环境


 作为Android开发人员,你首先要确保你的Android Studio没有问题,然后才是在Android Studio上配置Flutter的开发环境,下面我们先通过命令行检测一下。Win + R回车,输入cmd,回车,输入flutter doctor,回车。

be4d755bbd124c42a739e2bb522c2742.png


然后再往下滑动看看。06ee5344ef9b45c6958c19fb9875149f.png


 这条指令会检查电脑上的环境,Android Studio是没有问题的,连接设备也没有问题,网络也没有问题,现在我们的Android Studio还不支持Flutter的,因此我们需要支持它,打开Android Studio。File → Settings → Plugins ,输入Flutter。

d4c48f562e1c45899d62b2eb30ba68d8.png


 可以看到Flutter实际上作为插件进行安装,我们点击Install进行安装,会弹出一个弹窗。

75e3bb9c97da40b7a409ea57d1a70ef2.png


 提示你安装Flutter之前需要安装Dart插件,因为Flutter使用的是Dart语言,因此点击Install让他去安装。

9149f3d2efa94d308502c57777314828.png


 安装好之后点击Restart IDE重新启动Android Studio,让我们刚才安装的插件生效。


四、运行hello_world项目


 我们之前下载的Flutter SDK里面有一个examples文件夹,里面是一些flutter项目,这些项目有什么作用呢?首先是让你运行来检测本地的Flutter环境配置,然后就是可以让你快速的了解Flutter。

22a9502dd1324551b285df2d2fc6b2c9.png


我们通过Android Studio打开hello_world。点击Flie → Open。

48619189e0534fb59c14d1d72f8700c8.png


点击OK。

df88d4e8f65b4dd18270aed49119096b.png


点击Trust Project。

f14cf88b662f402ebe8de0e7575b61d9.png


 这就是我们的Flutter项目了,目前正在下载配置的内容,请稍等。发现项目有错误,我们打开lib下的main.dart

874bfb533b6947f395585bdec436aa8e.png


 这里提示你Dart SDK 没有配置,而其实我们下载Flutter SDK里面就带了Dart的SDK,因此我们先配置Flutter SDK,在Android Studio中配置Flutter的SDK,如图所示。

07ece10afdf44e7483870dfc138db91c.png


 配置好之后点击Apply按钮,再点击OK关闭这个窗口,你会看到当前的hello_world项目会再编译一次,我们再看main.dart。

ff118f6f7792402bb90365ac95290888.png


 点击Upgrade dependencies,更新依赖,更新完成之后,当前的main.dart中的内容就不会报错了。

25102533c82f4281b1aa2c85ef913645.png


 然后要运行起来就需要连接真机或者启动虚拟机了。启动模拟器之后我们发现了一个问题。

51ecc4d15ca64da28739e3bb951e74d9.png


 项目中似乎没有识别到这个模拟设备,这个时候要看是不是模拟器有问题,于是我打开Andoid项目,发现模拟机是可以识别到,那么问题就出来Flutter上,所以我们要为Flutter配置Android 的Sdk路径,关闭Android Studio,找到Android Sdk路径,我的Android Sdk所在路径是:D:\Android\Sdk,然后我们Win + R 弹窗,输入cmd,然后进入命令窗口,输入如下指令:

flutter config --android-sdk D:\Android\Sdk


回车

87a61361582c4906bc40cb0f09df6bf0.png


 配置好之后,这里会提示你重启编辑器,也就是Android Studio,我们重启Android Studio。再启动模拟器。

bc77b38d2600494b86eb99ce3f68e7f2.png


找到了设备。

e480a7d5d8fb4527907f4046b3e057fc.png


好了,下面运行一下。

96ce228c6dcd4bd9bbbe504e05e04ac0.png


 看日志好像和这个FlutterActivity有关,我们可以在AndroidManifest.xml中看到有注册这个FlutterActivity

5765fd625d244d158bf4ab6502e9523c.png


 Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present


 这里看这句话,定位 S+(版本 31 及更高版本)要求在存在意图过滤器时定义 android:exported 的显式值,因为我们的虚拟机是Android 12,而在Android12中,注册Activity时要加上android:exported属性,一般启动的设置为ture,其他设置为false,那么我们设置一下看看。

e57fb51bc80744b5b03bc3b2e5fb7625.png


再运行一下

02b74045a2f142afae9f485066263aeb.png


 运行起来了,下面我们再用真机运行试试看,通过USB数据线连接真机。

a8154f5d08354e51a70b4d52e66e9754.png


运行:

2becd91611af473a86b09cbc51868eeb.jpg


也可以运行成功。


 通过运行sdk中自带的项目我们解决了一些问题,同时还发现这个项目比较老旧了,没有做更新,它里面还是基于Android 10去写的,Android11上运行应该没有问题,而到了Android12上就不行了,好了,不研究它的demo了,下面我们要自己创建一个Flutter项目。


五、创建Flutter项目


点击File → New → New Flutter Project。

04a1dafd3cbc464c9f35949b9daa72e6.png


选择Flutter,点击Next。

570bfad4bc744517b87f1a06f5793ec0.png


创建一个HelloWrold项目。

e1244264e9c14a83b2c784fe86de8afa.png


 这里的项目名称必须以小写,下划线格式进行命名,让我觉得有一些不舒服,这里我修改了项目的存放路径,然后默认选择Android和iOS平台,语言使用Kotlin 和Swift,点击Finish。


项目创建完成,如下图所示:

f79e2fc50a5840d19a0aa404455cf20e.png


创建完成之后我们直接运行这个项目在模拟器或者真机上。

b392b97a2de54a9db92b8067029f2f6a.png


这是一个计数器,点击右下角的浮动按钮,屏幕中间的数字会加1。


六、Flutter工程结构


 现在工程已经运行起来了,对于一个新的项目工程,我们需要大概的之后它的结构内容,各个目录代表什么意思。

0ac34b21be99454a8702b17eea94c143.png


首先我们来看一下重点内容项目的目录。


.dart_tool


 这是一个dart工具文件夹,里面包含了flutter工程的构建信息,里面还有一个version文件,说明当前使用的flutter的版本,无需什么改动,了解就好。


.idea


 因为Android Studio 是由IDEA编辑器改过来的,因此会在创建项目时生成一个.idea文件夹,根据创建项目类型不同,它里面的内容就会不同,了解就好。


android


 Android的项目文件,作为Android开发者,想必你肯定知道这个android文件夹中的各个文件代表什么意思。


ios


 ios的项目文件,作为Android开发者,我不知道里面怎么操作的也很正常,嗯,暂时我们不考虑ios的问题。


lib


 这是Flutter应用源文件,里面有一个main.dart是程序入口文件,我们运行看到的第一个页面就在这里面,稍后会详细讲述这个main.dart文件。


test


 测试文件


.gitignore


 git忽略文件,就是这里面的文件在提交git时会忽略掉,一般来说就是一些编译时文件,例如build之类的。


.metadata


 用来记录Flutter 项目属性的的隐藏文件。


.packages


用来记录Flutter项目的包信息。


analysis_options.yaml


 静态分析文件。


hello_world.iml


 工程配置文件。


pubspec.lock


 记录当前项目实际依赖信息的文件。


pubspec.yaml


 管理第三方库及资源的配置文件。


README.md


 项目描述文件。


 基本的内容就说完了,这样看起来实际上Flutter工程就是一个同时内嵌了 Android 和 iOS 原生子工程的父工程,我们在 lib 目录下进行 Flutter 代码的开发,而某些特殊场景下的原生功能,则在对应的 Android 和 iOS 工程中提供相应的代码实现,供对应的 Flutter 代码引用。


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


七、Flutter开发核心思想


 我们运行程序之后发现是一个计数器Demo,在这个简单示例中,从基础的组件、布局到手势的监听,再到状态的改变,Flutter 最核心的思想在这 60 余行代码中展现得可谓淋漓尽致,也就是这个lib下的main.dart文件。


 我们来了解一下它在这里面做了什么?首先我们看一下main.dart中的代码:

import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
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: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}


 这个main.dart里面有很多的注释,我这里是把注释去掉了,你可以自己去了解它们的意思,从而了解这些代码是干什么的。


我们从上往下来看

import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}


 这里首先我们知道导了一个包,material是一个材料设计库,作为Android开发者你不会陌生,这说明这个页面是按照material风格设置的,然后是一个main()函数,里面通过runApp()函数执行一个app部件,也就是Widget,这里的部件就是MyApp()函数,然后我们再看MyApp()做了什么?

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}


 这里我们的MyApp是一个类,继承了StatelessWidget,这是一个无状态部件,然后实现构造方法,构造方法里面通过MaterialApp()函数定义风格,然后是标题、主题和主页面信息,这里主页面home中调用MyHomePage()函数,也就是我们当前页面所显示的内容。这里有一个Colors.blue,你试一下改成red,或者green。如果你这时候项目是运行在模拟器上或者真机上的话,你可以修改后Ctrl + S 进行保存。

2d2f70b2ec31417db568bb0c0693d09b.png


 然后就会直接将你刚才改动的渲染到设备上,这叫热重载,这是Flutter中很方便的一个功能,还有一点就是,你注意到模拟器上方这个黄色的闪电图标没有。

8dee737c927a4cad9f6f683ac6428d6b.png


 你改动后,点击它和Ctrl + S效果是一样的。比如我们再改成green,然后点击这个闪电图标。

1aa7d6d0c6ef471693de1369a06d0183.png


然后我们继续往下看。

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


 这里MyHomePage继承StatefulWidget,这是一个有状态的部件,这里就需要一个状态了,通过createState()得到一个_MyHomePageState,这个_MyHomePageState()就是这个页面的主要内容了,它里面是

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: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}


 这里_MyHomePageState 继承了State< MyHomePage >,创建一个_counter 变量,默认是0,我们运行时看到的就是0,通过_incrementCounter()函数调用setState(),再这里面进行_counter自增,再往下看就是build()构造函数,在 build 方法中,我们通常通过对基础 Widget 进行相应的 UI 配置,或是组合各类基础 Widget 的方式进行 UI 的定制化。


 这里返回一个Scaffold,这是一个脚手架,用来构建页面,如果你有过Compose的开发经验,那么你会觉得熟悉,当然了Compose其实就是向Flutter看齐,只不过Compose是在Android原生中进行声明式UI设计,简化页面,大体思路和Flutter差不多。


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


 这里主要的内容是值的变化和浮动按钮的点击,也就是$_counter进行赋值,onPressed表示浮动按钮按下,按下后会执行_incrementCounter,然后调用setState函数,setState 函数是 Flutter 以数据驱动视图更新的关键函数,它会通知 Flutter 框架,因为它里面_counter++,所以数据发生变化,通过刷新界面。而 Flutter 框架收到通知后,会执行 Widget 的 build 方法,根据新的状态重新构建界面。


 这个思路其实你可以类比DataBinding,页面和数据相关,但是它是单向的,通过状态来控制页面UI改变,这就是显示比较新的一个框架了,MVI框架。


 如果你深刻的理解了这个实例,那么你就知道了Flutter的核心思想,不要去计较某一个API的使用方式,陷在里面就得不偿失了,从全局出发。


尾声


 开始Flutter的学习之旅,你是否感觉到兴奋呢?


相关文章
|
4月前
|
Dart 搜索推荐
Flutter入门进阶之旅(二)Hello Flutter
好像几乎我们学习或者掌握任何一门编程语言都是Hello word开始的,本篇博文做为Flutter入门进阶的第一篇分享,我们也从最简单的Hello world开始,至于Flutter开发环境的配置,跟关于Dart语言的介绍,不是该专栏要讲解的内容,我就不详细做介绍了,读者可自行google或者百度了解一下。
47 0
|
Android开发
【错误记录】Flutter 混合开发报错 ( java.nio.file.FileSystemException: xxx/R.jar: 另一个程序正在使用此文件,进程无法访问。 )
【错误记录】Flutter 混合开发报错 ( java.nio.file.FileSystemException: xxx/R.jar: 另一个程序正在使用此文件,进程无法访问。 )
680 0
【错误记录】Flutter 混合开发报错 ( java.nio.file.FileSystemException: xxx/R.jar: 另一个程序正在使用此文件,进程无法访问。 )
|
开发框架 Dart 前端开发
如何使用 Flutter 创建桌面应用程序【Flutter 专题 1】
桌面应用程序在具有各种 UI 元素的系统窗口内运行。如果您要制作桌面应用程序,有多种不同的框架、UI 工具包和编程语言可供选择。 有两种类型的桌面应用程序开发 API:特定于平台的和跨平台的。特定于平台的 API 仅支持一种目标操作系统。例如,Cocoa API 提供了用于为 macOS 平台开发桌面应用程序的接口。另一方面,跨平台 API 允许开发人员使用单个通用 API 为多个操作系统制作桌面应用程序。
1452 0
如何使用 Flutter 创建桌面应用程序【Flutter 专题 1】
|
Dart 容器
flutter制作具有自定义导航栏的渐进式 Web 应用程序
本文主要介绍具有自定义导航栏的渐进式 Web 应用程序 gitee github 让我们准备我们的 - “Main.dart” 我们将整个页面分成几个部分,以便于制定,我建议您这样做以获得更好的编程,让我们更详细地查看这些部分, NavigationBar()、 DashBoard()、 CalendarSpace(), 首先我们可以做导航栏部分
154 0
|
Android开发
flutter hello world
flutter hello world
438 0
flutter hello world
|
开发工具 Android开发
Flutter 04: 图解第一个程序遇到的安装依赖问题
      小菜刚开始学习 Flutter 会遇到各种意想不到的问题,今天整理一下第一次新建项目运行时报的错的处理方式。     Finished with error: Please review your Gradle project setup in the android/folder.
2096 0
|
开发工具 Windows Dart
Flutter 03: 图解第一个程序 Hello World!
      无论是学习哪门语言,第一个程序都是 Hello World! 小菜最近在学习 Flutter 因此整理一下在第一个测试 Demo 中遇到的一些问题。
2360 0
|
1月前
|
Android开发 iOS开发 容器
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
鸿蒙harmonyos next flutter混合开发之开发FFI plugin
|
28天前
|
开发者
鸿蒙Flutter实战:07-混合开发
鸿蒙Flutter混合开发支持两种模式:1) 基于har包,便于主项目开发者无需关心Flutter细节,但不支持热重载;2) 基于源码依赖,利于代码维护与热重载,需配置Flutter环境。项目结构包括AppScope、flutter_module等目录,适用于不同开发需求。
69 3
|
13天前
|
传感器 开发框架 物联网
鸿蒙next选择 Flutter 开发跨平台应用的原因
鸿蒙(HarmonyOS)是华为推出的一款旨在实现多设备无缝连接的操作系统。为了实现这一目标,鸿蒙选择了 Flutter 作为主要的跨平台应用开发框架。Flutter 的跨平台能力、高性能、丰富的生态支持和与鸿蒙系统的良好兼容性,使其成为理想的选择。通过 Flutter,开发者可以高效地构建和部署多平台应用,推动鸿蒙生态的快速发展。
114 0