Flutter开发入门

276 阅读10分钟

1. 概述

什么是Flutter

Flutter 是一个开源的移动应用开发框架,由 Google 开发,旨在帮助开发者构建高性能、高品质的跨平台移动应用。Flutter 提供了丰富的组件、工具和库,使开发者能够以一套代码基础构建适用于 iOS、Android、Web 和桌面平台的应用程序。

###Flutter框架的优点:

  • 快速开发:Flutter 提供了热重载功能,允许开发者在应用程序运行时即时查看代码更改的效果,大大加速了开发周期。

  • 灵活性:Flutter 的组件灵活性极高,允许开发者根据需要自定义和组合组件,以满足不同的设计需求。

  • 高性能:Flutter 使用自绘引擎,能够实现高性能的渲染效果,并在各种平台上保持一致的性能表现。

  • 跨平台:Flutter 具有真正的跨平台能力,开发者可以使用相同的代码库构建多个平台上的应用程序,从而降低了开发和维护成本。

  • 接近原生性能:Flutter 不是通过 WebView 或 JavaScript 来渲染 UI,而是使用平台的原生控件进行渲染,因此具有接近原生应用程序的性能和体验。

Flutter框架的不足:

  • 生态没有原生Android或者IOS那么完善,有些需要的插件或者三方库缺失。

  • 性能没有原生丝滑,但已经接近原生体验,移动应用跨平台框架远胜于React Native

2. 开发环境和工具

配置环境:

在masOS下可以同时进行Android和iOS设备的测试。Windows电脑上不能运行调试ios设备。 具体配置可以见 book.flutterchina.club/chapter1/in…

开发IDE:

Android Studio、XCode、VSCode等。

可调试的手机设备:

Android 模拟器(依赖AndroidStudio提供的工具 ) IOS模拟器(依赖XCode提供的工具) Android手机(需要打开开发者权限,部分手机不一定能成功USB连接调试) IOS手机(IOS版本高似乎都不支持真机调试,即便能运行,在launch的时候也会退出)

开发语言

Dart 是一种由谷歌开发的面向对象、静态类型、可选的即时编译语言。它最初于2011年发布,旨在成为 Web、移动应用和服务器端等各种平台的通用编程语言。语法和主流的Java、Python、等待语言大体类似,以下是 Dart 语言的一些关键特点和概述:

  • 面向对象:Dart 是一种纯粹的面向对象编程语言,所有的值都是对象,而且支持类、继承、多态和抽象类等面向对象的特性。

  • 静态类型:Dart 是一种静态类型语言,但也支持类型推断。通过类型检查,可以在编译时捕获许多错误,从而提高代码的稳定性和可维护性。

  • 异步编程:Dart 内置了强大的异步编程支持,通过 async 和 await 关键字,开发者可以轻松地编写异步代码,处理事件和异步操作。

  • 库和包管理:Dart 提供了丰富的标准库和包管理工具(如 pub),可以轻松地引入和管理依赖库,提高了代码复用性和开发效率。

  • 跨平台:Dart 旨在成为一个通用的编程语言,可以在多种平台上运行,包括 Web、移动应用和服务器端。通过 Flutter 框架,可以使用 Dart 构建高性能、美观的移动应用。

Dart代码示例:

下面代码的示例,是app登录时调用接口的示例: 代码处理的逻辑依次是: 请求登录接口 -> 设置Token -> 处理消息推送 -> 请求app的菜单权限 -> 设置app需要用到的一些个人账户信息,存储在本地 -> 如果是第一次登录,需要重置密码 -> 请求按钮权限 -> 去到app首页

Service.pwdLogin(username: username, password: password)
    .then((value) async {
  if (value == null) return;
  //需要token请求修改密码接口,所以放在前面
  await setToken(value["accessToken"]);
  try {
    try {
      unawaited(SharedPreferenceService.instance
          .get(getuiClientId, '')
          .then(
              (cid) => MessageAsk.bindPush(cid, Get.locale!.languageCode)));
    } catch (e) {
      LogUtil.log('登陆绑定推送失败不处理');
    }
    //请求权限
    bool? menuRes = await BtnPermissionManager().loadMenuList();
    if (menuRes != true) {
      HYXLoading.showToast(LocaleKeys.loginFail.tr);
      await SharedPreferenceService.instance.remove(keyLoginToken);
      return;
    }
  } catch (e) {
    HYXLoading.showToast(LocaleKeys.loginFail.tr);
    await SharedPreferenceService.instance.remove(keyLoginToken);
    return;
  }
  //设置isOwner
  if (value["role"] != null && value["role"]["isOwner"] != null) {
    await setIsOwner(value["role"]["isOwner"]!.toString());
  }
  //判断是否是体验账号
  if (value["role"] != null && value["role"]["isExperience"] != null) {
    setIsExperience(value["role"]["isExperience"].toString());
    if (value["role"]["isExperience"].toString() == "0") {
      await setAccount(username);
    }
  }
  //设置isBSOwner
  if (value["role"] != null && value["role"]["isBSOwner"] != null) {
    var bsOwner = value["role"]["isBSOwner"]!;
    _isBSOwner = bsOwner == 1;
    await setIsBSOwner(bsOwner);
  }
  // 1 第一次登陆 0:不是第一次登陆
  if (value["loginFirst"]?.toString() == "1") {
    //要去重置密码
    HYXLoading.showToast(LocaleKeys.loginSucceededResetPasswordFirst.tr);
    await HYXRoutePushUtil.pushName(RouteManager.registerSetPwd,
        arguments: SetPwdParamModel(systemPwd: password));
  } else {
    await _setLoginState(true);
    unawaited(HYXRoutePushUtil.changeRootPage());
  }
  unawaited(Provider.of<BtnPermissionProvider>(
          AppShare.instance.rootContext,
          listen: false)
      .loadAllButtonsPermission());
});

Dart语言值得注意的地方

(1)空安全性:

Dart 2.12 版本引入了空安全性,使得变量可以明确指定是否可以为空。因此,在编写 Dart 代码时,应该注意对于可能为空的变量进行合适的处理,以避免空指针异常。

String name = 'Alice';
String? email;

print('Name: $name');

if (email != null) {
print('Email: $email');
} else {
print('Email is not provided.');
}

(2)支持异步编程:

Dart 提供了强大的异步编程支持,包括 async 和 await 关键字、Future 类型等,使开发者能够轻松处理异步操作,编写高效的异步代码。

Future<String> fetchUserData() async {
  // 模拟异步操作,比如从网络获取数据
  await Future.delayed(Duration(seconds: 2));
  return 'Name: Alice, Email: alice@example.com';
}

(3)单线程语言:

Dart 作为一个单线程语言,虽然提供了多线程的机制,但是在多线程的资源是隔离的,两个线程之间资源是不互通的。

Dart 的多线程数据交互需要从 A 线程传给 B 线程,再由 B 线程返回给 A 线程。而像 Android 在主线程开一个子线程,子线程可以直接拿主线程的数据,而不用让主线程传给子线程。

由于 Dart 是单线程语言,因此在执行代码时不会出现多线程竞争资源的情况,这样可以避免许多常见的多线程问题,如死锁、竞态条件等。

为了解决长时间运行操作导致 UI 阻塞的问题,Dart 提供了异步编程特性,如 Future、async 和 await,允许开发者在主线程中发起异步操作,然后在操作完成时得到通知并处理结果,而不会阻塞主线程的执行。

总的来说,Dart 的单线程模型通过事件循环和异步编程特性,提供了一种简单而有效的方式来处理并发和异步操作,同时避免了多线程编程中常见的问题。

3.使用Flutter编写一个简单页面:计数器示例

截图: 转存失败,建议直接上传图片文件 代码示例

import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState 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>[
            Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

4.使用Flutter进行移动应用管理

###(1)状态管理 Flutter 状态管理是指在 Flutter 应用中有效地管理应用的数据和状态,以确保用户界面(UI)与数据之间的一致性和交互性。在复杂的应用中,数据通常会在不同的部分之间流动和变化,而状态管理的目标是帮助开发者更好地组织、更新和共享这些数据。

状态管理作用
  • 数据共享和同步:在应用程序中,不同部分可能需要共享和同步数据。通过状态管理,可以轻松地在应用程序的各个部分之间共享数据,并确保数据的一致性。
  • UI更新:Flutter状态管理可以帮助开发者管理应用程序中的UI状态,以便在数据变化时更新用户界面。这样可以确保应用程序的UI与数据的状态保持同步。
  • 复杂状态管理:随着应用程序变得越来越复杂,管理应用程序的状态变得更加困难。Flutter状态管理工具可以帮助开发者更有效地管理应用程序的状态,使代码更具可维护性和可扩展性。
  • 性能优化:有效的状态管理可以帮助应用程序避免不必要的重绘和重新构建,从而提高应用程序的性能和响应速度。
  • 代码结构:通过良好的状态管理,开发者可以更好地组织应用程序的代码结构,使其更易于理解和维护。

下面是使用比较多的状态管理方法及优缺点:

1. Provider

轻量级、易学习、内置于Flutter中,适用于基本状态管理。 pub.dev/packages/pr…

在使用Provider的时候,我们主要关心三个概念: ChangeNotifier:真正数据(状态)存放的地方 ChangeNotifierProvider:Widget树中提供数据(状态)的地方,会在其中创建对应的ChangeNotifier Consumer:Widget树中需要使用数据(状态)的地方

更多 : juejin.cn/post/684490…

2. flutter_bloc 

基于块模式构建,将业务逻辑与用户界面解耦,适用于复杂的状态管理。 pub.dev/packages/fl…

3. Get

简单易用:

GetX提供了简洁而直观的API,使得状态管理和导航等功能变得非常容易实现。 开发者可以通过少量的代码实现复杂的功能,提高开发效率。

性能优秀:

GetX被设计为高性能的状态管理库,具有出色的性能表现。 GetX使用响应式编程和观察者模式,可以确保只有在数据变化时才会触发UI更新,从而提高应用程序的性能。

路由管理:

GetX提供了强大的路由管理功能,支持命名路由、动画过渡等。 开发者可以轻松地管理应用程序的导航逻辑,实现页面之间的切换和传递参数。

轻量级:

GetX是一个轻量级的库,不会给应用程序增加过多的负担。 使用GetX可以避免引入过多的依赖,使应用程序保持简洁和高效。

pub.dev/packages/ge…

###(2)路由管理 简单来说,路由管理就是页面之间如何调整、传递参数等一系列操作。

  • GetX,get提供了一套路由管理
  • 系统自带的Navigator
  • 其他三方插件提供的路由管理。

###(3)数据持久化管理 app本地也是可以存储数据的,有以下几种数据存储类型:

Shared Preferences:

这是一种轻量级的键值对存储方案,用于存储小量的简单数据,例如用户偏好设置、应用程序配置等。Shared Preferences 使用异步 API 进行读写操作,可以在整个应用程序中共享数据。

文件存储:

你可以将数据存储在文件中,这对于存储结构化数据或大量数据很有用。Flutter 提供了文件操作的 API,包括读取、写入、删除和查询文件等操作。你可以使用 JSON、CSV、SQLite 等格式来组织和存储数据。

SQLite 数据库:

如果你需要在 Flutter 中使用关系型数据库,可以使用 SQLite。Flutter 提供了 sqflite 插件,它是 SQLite 数据库的 Flutter 封装。你可以使用 sqflite 插件执行 SQL 查询、插入、更新和删除操作,以及管理数据库表结构。

Hive 数据库:

Hive 是一个轻量级的、快速的、键值型的数据库,适用于在 Flutter 中存储结构化数据。Hive 使用自定义的二进制格式来存储数据,因此比 SQLite 更快。它还提供了方便的查询和过滤功能。

5.常用的三方库

加载网络图片同时进行缓存

cached_network_image 3.3.1  pub.dev/packages/ca…

加载h5页面

webview_flutter: ^4.7.0 pub.dev/packages/we…

语言国际化

intl: ^0.19.0 pub.dev/packages/in… 或者:Get

获取手机定位

geolocator: ^11.0.0 pub.dev/packages/ge…