Flutter 3 跨平台应用开发:从 Widget 到发布

FreeGuideOnline 最新 2026-06-12

Flutter 3 跨平台应用开发实战:从 Widget 到发布

环境准备与项目初始化

安装 Flutter SDK

Flutter 官网 下载最新稳定版 SDK,解压后将其 bin 目录添加到系统 PATH。在终端执行 flutter doctor 检查环境依赖,根据提示安装缺失的组件(如 Android Studio、Xcode、Chrome 等)。确保所有检查项均为绿色勾选状态。

创建第一个 Flutter 项目

打开终端,执行以下命令创建项目:

flutter create my_first_app

进入项目目录,使用你喜欢的 IDE(推荐 VS Code 或 Android Studio)打开。项目结构如下:

  • lib/main.dart:应用入口文件,所有 Dart 代码都写在这里或其导入的文件中。
  • pubspec.yaml:配置文件,用于声明项目依赖、资源等。
  • android/ios/:原生工程目录,多数情况下无需手动修改。

main.dart 中,默认模板已经包含了一个简单的计数器应用。我们先运行它来验证环境是否正常。

flutter run

选择一个连接的设备(模拟器或真机),应用将启动并展示一个带浮动按钮的页面。

理解 Widget 体系:一切皆为组件

Widget 的核心概念

Flutter 中所有 UI 元素都是 Widget,从文本、按钮到整个页面。Widget 分为两大类:

  • StatelessWidget(无状态组件):UI 静态不变,依赖外部数据一次性构建。
  • StatefulWidget(有状态组件):内部持有可变状态,状态变化时触发界面重绘。

入门时重点掌握如何组合和嵌套 Widget,构建出想要的布局。

基础布局 Widget

// 一个简单的个人卡片界面
Scaffold(
  appBar: AppBar(title: Text('个人名片')),
  body: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        CircleAvatar(
          radius: 60,
          backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
        ),
        SizedBox(height: 16),
        Text(
          'Flutter 开发者',
          style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 8),
        Text('专注移动跨平台技术', style: TextStyle(color: Colors.grey)),
      ],
    ),
  ),
)

以上代码展示了 Scaffold(页面骨架)、CenterColumnSizedBox 等常用布局组件。通过组合这些无状态组件,可以快速搭建静态界面。

引入状态:StatefulWidget

当界面需要响应用户交互或数据变化时,使用 StatefulWidget。以下是一个数字增减的示例:

class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        IconButton(
          icon: Icon(Icons.remove),
          onPressed: () => setState(() { _count--; }),
        ),
        Text('$_count', style: TextStyle(fontSize: 30)),
        IconButton(
          icon: Icon(Icons.add),
          onPressed: () => setState(() { _count++; }),
        ),
      ],
    );
  }
}

调用 setState() 会通知框架重新执行 build 方法,并仅更新发生变化的部分。

导航与路由管理

基本页面跳转

使用 Navigator 进行页面间的切换。最简单的跳转:

// 跳转到新页面
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondPage()),
);

// 返回上一页
Navigator.pop(context);

命名路由

对于复杂应用,推荐在 MaterialApp 中定义命名路由表:

MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => HomePage(),
    '/details': (context) => DetailPage(),
  },
)

页面内使用 Navigator.pushNamed(context, '/details') 跳转。

传递参数

传递简单参数:在路由的 builder 函数中直接接收构造参数。使用命名路由时,可通过 onGenerateRoute 解析参数:

onGenerateRoute: (settings) {
  if (settings.name == '/details') {
    final args = settings.arguments as Map;
    return MaterialPageRoute(
      builder: (context) => DetailPage(data: args['data']),
    );
  }
}

在源页面调用时传入参数:

Navigator.pushNamed(context, '/details', arguments: {'data': someData});

网络请求与数据处理

添加 http 依赖

pubspec.yaml 中添加:

dependencies:
  http: ^1.1.0

执行 flutter pub get 安装。

发送 GET 请求并解析 JSON

import 'dart:convert';
import 'package:http/http.dart' as http;

Future<List<Post>> fetchPosts() async {
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
  if (response.statusCode == 200) {
    List jsonData = jsonDecode(response.body);
    return jsonData.map((json) => Post.fromJson(json)).toList();
  } else {
    throw Exception('Failed to load posts');
  }
}

class Post {
  final int id;
  final String title;
  final String body;

  Post({required this.id, required this.title, required this.body});

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }
}

界面展示异步数据

使用 FutureBuilder 优雅处理异步数据:

FutureBuilder<List<Post>>(
  future: fetchPosts(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    } else if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    } else {
      return ListView.builder(
        itemCount: snapshot.data!.length,
        itemBuilder: (context, index) => ListTile(
          title: Text(snapshot.data![index].title),
          subtitle: Text(snapshot.data![index].body),
        ),
      );
    }
  },
)

状态管理入门:Provider 模式

安装 Provider

pubspec.yaml 中添加:

dependencies:
  provider: ^6.1.1

创建数据模型与 ChangeNotifier

import 'package:flutter/material.dart';

class CartModel extends ChangeNotifier {
  List<String> _items = [];

  List<String> get items => _items;

  void add(String item) {
    _items.add(item);
    notifyListeners();
  }

  void remove(int index) {
    _items.removeAt(index);
    notifyListeners();
  }
}

在顶层注入并消费

main.dart 中使用 ChangeNotifierProvider 包裹 MaterialApp

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => CartModel(),
      child: MyApp(),
    ),
  );
}

在任意后代 Widget 中读取和操作状态:

// 读取
final cart = context.watch<CartModel>();
// 触发方法
context.read<CartModel>().add('商品A');

本地数据持久化:SharedPreferences 与 SQLite

使用 SharedPreferences 存储键值对

依赖:

dependencies:
  shared_preferences: ^2.2.2

保存与读取:

final prefs = await SharedPreferences.getInstance();
// 保存
await prefs.setString('username', 'FlutterDev');
// 读取
String? username = prefs.getString('username');

适用于简单配置、用户偏好等。

使用 sqflite 管理结构化数据

依赖:

dependencies:
  sqflite: ^2.3.0
  path: ^1.8.3

初始化数据库并创建表:

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

Future<Database> openDatabase() async {
  final dbPath = await getDatabasesPath();
  return openDatabase(
    join(dbPath, 'app.db'),
    onCreate: (db, version) {
      return db.execute(
        'CREATE TABLE notes(id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT)',
      );
    },
    version: 1,
  );
}

插入、查询、删除等操作使用 insertquerydelete 方法,与原生 SQLite 类似。

界面美化与适配

主题定制

MaterialApp 中设置全局主题:

MaterialApp(
  theme: ThemeData(
    primarySwatch: Colors.indigo,
    visualDensity: VisualDensity.adaptivePlatformDensity,
    textTheme: TextTheme(
      headline6: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
    ),
  ),
)

单个界面也可以通过 Theme.of(context) 动态获取主题色,保持风格一致。

响应式布局

使用 MediaQuery 获取屏幕尺寸,或借助 LayoutBuilder 按父级约束调整布局。例如,平板采用左右分栏,手机使用竖排:

LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth > 600) {
      return Row(children: [Expanded(child: leftPanel), Expanded(child: rightPanel)]);
    } else {
      return Column(children: [leftPanel, rightPanel]);
    }
  },
)

构建与发布

生成 Android APK / App Bundle

在终端执行:

flutter build apk --release

APK 文件位于 build/app/outputs/flutter-apk/app-release.apk

如需上传到 Google Play,生成 App Bundle:

flutter build appbundle --release

构建 iOS 应用

需要 macOS 环境和 Xcode。打开 ios/Runner.xcworkspace,在 Xcode 中配置签名团队,然后执行:

flutter build ipa --export-method app-store

生成的 .ipa 文件可通过 Transporter 或命令行上传到 App Store Connect。

应用图标与启动页

替换图标可使用 flutter_launcher_icons 包。在 pubspec.yaml 中配置后运行命令即可自动生成各尺寸图标。

启动页(闪屏页)可在原生工程中修改,或使用 flutter_native_splash 包快速定制。

版本管理与更新

pubspec.yaml 中修改 version 字段,例如 version: 1.0.1+2,其中 1.0.1 是版本名,+2 是版本号(数字递增)。打包时此信息会嵌入应用。


学习路径建议

  1. 基础:彻底掌握 Dart 语言基础(变量、函数、异步、类)。
  2. 界面:熟练使用 Material 组件、布局系统、列表。
  3. 交互:学习表单、手势、动画。
  4. 架构:理解状态管理方案(Provider 后可选 Riverpod、Bloc)。
  5. 工程化:掌握网络、存储、路由、国际化。
  6. 发布:测试、性能优化、打包上线。

跟随本教程,从零搭建一个完整应用并发布到应用商店,是巩固技能的最佳方式。立即动手,开启你的 Flutter 跨平台开发之旅吧!