Flutter开发之基础知识

49次阅读

共计 6280 个字符,预计需要花费 16 分钟才能阅读完成。

作为时下最留下的大前端跨平台开发框架,很多的公司和同学都开始了 Flutter 学习和应用,关于 Flutter 的基础知识,可以参考下面的两篇文章。
Flutter 环境搭建
Flutter 基础知识点总结

接下来,我们将介绍一些 Flutter 应用开发中一些基本的知识。

Flutter 基础知识

创建 Flutter 项目

在 Flutter 开发中,创建一个 Flutter 项目通常有以下两种方式:

  • 使用 flutter create 命令,确保 Flutter SDK 配置了环境变量。
  • 使用安装了 Flutter 和 Dart 插件的 IDE,如 Android Studio 和 IntelliJ IDEA。

命令行方式创建 Flutter 的命令如下:

flutter create <projectname>

如果使用 IDE 创建 Flutter 项目,可以依次选择【File】->【New】->【New Flutter Project…】,如下图所示:

运行项目

在 Flutter 开发中,运行 Flutter 项目主要有两种方式,一种是命令方式,一种是 IDE 的方式。
命令方式运行 Flutter 如下所示:

flutter run -d 'iPhone X'
flutter run -d emulator-5554

其中,- d 后面跟的是具体的设备名称,可以是 Android 或 iOS 模拟器的名字,也可以一台已经连接到电脑上的 Android 或 iOS 的设备。
相比命令方式,我们更推荐使用 IDE 图形化工具的方式,首先选择要运行的设备,然后选择 main.dart 入口文件,然后点击【运行】按钮即可运行 Flutter 项目,如下图:

除了上面的命令外,Flutter 开发中常见的命令还有:

flutter emulator             // 查看本地模拟器
flutter emulators --create --name xyz        // 创建一个模拟器
flutter emulators --launch <emulator id>       // 启动模拟器
flutter build apk;           // 打包 Android 应用
flutter build apk –release;
flutter install;              // 安装应用
flutter build ios;            // 打包 IOS 应用
flutter build ios –release;
flutter clean;               // 清理重新编译项目
flutter upgrade;            // 升级 Flutter SDK 和依赖包
flutter channel;            // 查看 Flutter 官方分支列表和当前项目使用的 Flutter 分支
flutter channel < 分支名 >;   // 切换分支

除此之外,我们还可以点击 热重载按钮 (带有闪电⚡️图标的按钮)来开启热重载方法,如下图:

Flutter 调试

Flutter 提供了各种各样的工具和功能来帮助开发者调试 Flutter 应用程序,如果你使用的是 VsCode 作为开发工具,那么可以参考下面的调试技巧:

断点调试

在 Flutter 进行断点调试非常简单,只需要在 Vscode 上打上一个断点,按 F5 就会停在断点处。通过左边的调试栏,观察断点处的变量以及栈堆情况。

debugger 调试

debugger 代码调试只能运行在开发阶段,debugger 调试是 Flutter 提供的 debugger API,和 JavaScript 的 console 类似。例如:

import 'dart:developer';

void someFunction(double offset) {debugger(when: offset > 30.0, message: 'offset 大于 30 时,中断');
    // ...
}

那么,当 offset 这个变量的值大于 30.0 时中断运行,并输出 message 的内容。

rendering 调试

rendering 调试即开启布局线调试,当打开 rendering 时会在界面上看到一些布局线,以便于修复布局效果。要开启 rendering 调试,需要在代码中添加 debugPaintSizeEnabled。例如:

import 'package:flutter/rendering.dart';

void main() {
    debugPaintSizeEnabled = !true;
    runApp(new MyApp());
}

然后,重新运行项目即可看得效果。

日志调试

日志调试是软件开发中的一种很常见的调试方式,可以方便开发者查看程序运行的日志信息,现在流行的 IDE 几乎都集成了日志模块。Android Studio 和 Vscode 里的控制台 / 调试控制台都可以看到。

当然,为了方便,我们也可以自己定义一个 Debug 类用于代码调试,例如:

class Debug {static log(String tag, String text) {print('[$tag] $text');
    }
    static info(String tag, String text) {print('[$tag] $text');
    }
    static success(String tag, String text) {print('[$tag] $text');
    }
    static error(String tag, String text) {print('[$tag] $text');
    }
}

真机调试

在 Android 真机上运行 Flutter 程序,需要先开启开发者选项,开启的步骤如下:

  • 打开【开发者选项】和【USB 调试】。
  • 使用 USB 将手机连接电脑,若手机出现提示,授权电脑访问手机。
  • 在命令执行 flutter devices 确认连接电脑的设备。
  • 然后使用 flutter run 命令运行 app。
  • 在手机上开启 USB 调试模式。

Hello Word

和很多的程序一样,Flutter 程序也有一个启动页面,新建项目时系统默认的启动页面是 main.dart,那么我们可以修改 main.dart 的代码。例如:

import 'package:flutter/material.dart';
 
void main() => runApp(new MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      theme: new ThemeData(primaryColor: Colors.white,),
      home: new Scaffold(
        appBar: new AppBar(title: new Text('Welcome to Flutter'),
        ),
        body: new Center(child: new Text('Hello World'),
        ),
      ),
    );
  }
}

然后,运行上面的代码,可以看到如下的效果:

Flutter 项目结构

打开新建懂得 Flutter 工程,项目结构如下图所示:

可以发现,一个完整的 Flutter 项目目录结构如下:

┬
└ projectname
  ┬
  ├ android      - Android 部分的工程文件
  ├ build        - 项目的构建输出目录
  ├ ios          - iOS 部分的工程文件
  ├ lib          - 项目中的 Dart 源文件
    ┬
    └ src        - 包含其他源文件
    └ main.dart  - 自动生成的项目入口文件,类似 RN 的 index.js 文件
  ├ test         - 测试相关文件
  └ pubspec.yaml - 项目依赖配置文件类似于 RN 的 package.json

其中,对于开发者来说,比较重要的有以下几个文件:

  • android:android 平台相关代码;
  • ios:ios 平台相关代码;
  • lib:flutter 相关代码,也是 Flutter 项目源码存放的地方;
  • test:存放测试代码;
  • pubspec.yaml:配置文件,一般存放一些第三方的依赖。

入口函数

我们知道,每个应用程序都有一个入口函数,Flutter 项目的入口函数就是 main.dart 文件的 main 函数。

void main() => runApp(MyApp()); 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(...);
  }
}

在上面的代码中,返回了一个 MaterialApp widget,MaterialApp 可以理解为是 UI 的风格,MaterialApp 是 Android 使用的风格,iOS 则可以使用 CupertinoApp 风格。

Flutter 主题

除了 MaterialApp 样式外,我们还可以使用全局主题或使用 Theme 来定义应用程序局部的颜色和字体样式。

全局主题

创建应用主题的方法是将 ThemeData 提供给 MaterialApp 构造函数,如果没有提供主题,Flutter 将创建一个默认主题,全局主题的使用示例如下:

 new MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        brightness: Brightness.light,
        primarySwatch: Colors.blue,
        primaryColor: Colors.cyan[600]
      ),
    );

局部主题

除了全局主题外,Flutter 还支持创建特有的主题(局部主题)。具体使用时,数据实例化一个 ThemeData 并将其传递给 Theme 对象即可,如下所示:

new Theme(data: new ThemeData(accentColor: Colors.yellow), child: null),

当然,还可以扩展父主题,扩展父主题时无须覆盖所有的主题属性,可以通过使用 copyWith 方法来实现,例如:

floatingActionButton: new Theme(data: Theme.of(context).copyWith(accentColor: Colors.amber),
        child: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      ),

Flutter Widget

无状态组件和有状态组件

Flutter 将组件分为无状态和有状态两种。其中,无状态组件 (StatelessWidget) 是不可变的,这意味着它们的属性不能改变,所有的值都是最终的。有状态组件 (StatefulWidget) 持有状态可能在 Widget 生命周期中发生变化。

再平时开发中,使用得最多的应该就是有状态组件,要实现一个 StatefulWidget 至少需要两个类:

  • 一个 StatefulWidget 类,StatefulWidget 类本身是不变的;
  • 一个 State 类,在 Widget 生命周期中始终存在。

例如,官方给出的示例就使用了有状态组件。

创建可重用组件

组件一般是在设计和实现阶段由一些类或者模块组成的群组。每个组件完成一个独立的功能, 并且都有一个和其它组件的良好接口。可重用组件是指通过对以往组件进行局部修改或者不修改就可以组成新的软件,可重用组件是可重用软件的基础。

在 Flutter 开发中,创建可重用组件的方式有很多,最简单就是通过参数的方式,创建一个可以重用的组件,例如:

// Flutter
class CustomCard extends StatelessWidget {
  CustomCard({@required this.index, @required 
     this.onPress});

  final index;
  final Function onPress;

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: <Widget>[Text('Card $index'),
          FlatButton(child: const Text('Press'),
            onPressed: this.onPress,
          ),
        ],
      )
    );
  }
}

然后,在使用的时候,按照参数传入相应的值即可。

    ...
// Usage
CustomCard(
  index: index,
  onPress: () {print('Card $index');
  },
)
    ...

资源管理

再原生应用开发过程中,Android 和 iOS 都有特定的资源管理文件。虽然 Android 将 resources 和 assets 区别对待,但在 Flutter 中它们都会被作为 assets 处理,所有存在于 Android 上 res / drawable- * 文件夹中的资源都放在 Flutter 的 assets 文件夹中。

与 Android 类似,iOS 同样将 images 和 assets 作为不同的东西,而 Flutter 中只有 assets。被放到 iOS 中 Images.xcasset 文件夹下的资源在 Flutter 中被放到了 assets 文件夹中。

在 Flutter 开发中,assets 是资源文件的统一称呼,可以用来表示任意类型的文件,而不仅仅是图片。例如,你可以把 json 文件放置到 my-assets 文件夹中,将图片放到 image 文件中。

如果要访问 my-assets 的文件,可以使用 AssetBundle 来访问它,如下所示:

import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {return await rootBundle.loadString('my-assets/data.json');
}

在原生 Android 开发中,我们将不同分辨率的图片放到不同的图片文件夹下,如下所示:

  • mipmap-ldpi 0.75x
  • mipmap-mdpi 1.0x
  • mipmap-hdpi 1.5x
  • mipmap-xhdpi 2.0x
  • mipmap-xxhdpi 3.0x
  • mipmap-xxxhdpi 4.0x

iOS 的图片则有 1.0x,2.0x 和 3.0x 之分,不同分辨率的手机会自动加载对应分辨率的图片。

对应 FLutter 图片来说,我们也可以参考这种规则,把 1.0x 的图片放到 images 文件夹,将 2.0x
的图片放到另外的文件夹中,如下所示:

images/my_icon.png       // Base: 1.0x image
images/2.0x/my_icon.png  // 2.0x image
images/3.0x/my_icon.png  // 3.0x image

包管理

和原生 Android 和 iOS 应用开发一样,Flutter 的第三方库文件都在 pubspec.yaml 文件中,如果要使用某个第三方库,可以打开包仓库地址进行搜索,如下图所示:

下面以依赖 url_launcher 第三方库为例,使用步骤如下:

1,打开 pubspec.yaml 文件,在 dependencies 下添加包的名称和版本:

url_launcher: ^5.1.1

2,然后,点击 Packages get 命令来获取工程配置文件中的所添加的引用包,或者打开命令窗口执行 flutter packages get 命令,如下图:

3,然后,打开 main.dart 文件,导入 url_launcher.dart 包,并使用 launch 方法来打开 url 地址,如下所示:

import 'package:url_launcher/url_launcher.dart';

const url = "https://www.baidu.com";
launch(url);

正文完
 0