Flutter入门(面向Java/SpringBoot团队,快速上手)
Dart语法非常接近Java,类、泛型、函数、异常、OOP思想基本一致 ,你们团队上手会很快。
Flutter核心概念:一切都是Widget(组件),页面、按钮、文字、布局全是Widget,类似Java的组件/对象。
一、环境搭建(Windows,优先开发安卓APK)
1. 必备软件清单
- Git for Windows(加到PATH)
- Android Studio(提供Android SDK、模拟器)
- VS Code(写Flutter代码,推荐)
- Flutter SDK(官网下载压缩包,解压,把
flutter\bin加入系统环境变量PATH)>
2. 校验环境
打开PowerShell执行:
flutter doctor
它会自动检测缺失依赖,按提示补全。
- Android部分提示 ✅ 就可以跑安卓模拟器;
- iOS开发打包IPA必须Mac电脑,Windows只能开发安卓。
3. VS Code插件
搜索安装:Flutter(自动带Dart插件)
- 快捷键
Ctrl+Shift+P调出命令面板,可以直接新建Flutter项目
4. 创建项目
# 终端执行,新建项目
flutter create bus_app
cd bus_app
# 启动(自动识别模拟器/手机)
flutter run
- 热重载:按
r,不用重启APP,页面实时刷新(开发神器) flutter create --empty bus_app:生成极简空白模板,适合入门
二、项目目录重点(只看核心,其他不用管)
bus_app/
├── lib/ # 【全部业务代码在这里】
│ └── main.dart # 入口文件,程序main函数(类似Java main)
├── pubspec.yaml # 依赖配置!等价 Maven pom.xml / gradle
├── android/ # 安卓原生工程,打包APK用
├── ios/ # iOS工程(Mac打包IPA)
└── build/ # 编译产物
pubspec.yaml:添加第三方包(网络、websocket、图表),flutter pub get拉取依赖,类似mvn install
三、Dart基础(Java视角快速理解)
// main入口,程序起点
void main() {
runApp(const MyApp()); // 启动APP,根Widget
}
// 无状态组件:页面不会动态变数据(类似静态页面)
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '公交运维APP',
home: Scaffold(
appBar: AppBar(title: const Text("车辆监控")),
body: const Center(child: Text("Hello Flutter")),
),
);
}
}
class:和Java类几乎一样,支持继承、构造函数final / const:类似Javafinal,不可变- 两种Widget
StatelessWidget:无状态,页面渲染完不变,静态页面StatefulWidget:有状态,数据变化自动刷新UI(告警列表、实时车辆数据用这个,重点!)
基础布局(最常用,写页面必学)
Column:垂直排列(纵向,类似LinearLayout vertical)Row:水平排列(横向,LinearLayout horizontal)Container:容器,设置宽高、背景、圆角(类似View)Expanded:占剩余空间(权重布局)ListView:滚动列表(你的告警列表、车辆列表核心组件)
示例:垂直布局放文字+按钮
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("车辆编号:沪B12345"),
SizedBox(height:20), // 空白间距
ElevatedButton(
onPressed: (){
// 按钮点击事件,类似Java onClick
},
child: Text("查看告警"),
)
],
)
四、对接你的SpringBoot后端(重点)
1. 引入http包(GET/POST请求,调用SpringBoot接口)
修改 pubspec.yaml
dependencies:
flutter:
sdk: flutter
http: ^1.2.1
终端拉包:
flutter pub get
2. 最小Demo:请求SpringBoot接口,获取车辆数据
import 'package:http/http.dart' as http;
import 'dart:convert';
// 请求SpringBoot后端接口
Future<List> fetchBusList() async {
// SpringBoot接口地址
final res = await http.get(Uri.parse("[http://127.0.0.1:8080/api/bus/list](http://127.0.0.1:8080/api/bus/list)"));
if(res.statusCode == 200){
// json解析,和Jackson解析DTO思路一致
return jsonDecode(res.body);
}else{
throw Exception("请求失败");
}
}
async / await:Dart异步,类似Java CompletableFuture,非常适合网络请求。
3. WebSocket(接收实时车辆告警!你们业务核心)
用包 web_socket_channel,订阅SpringBoot的WebSocket,实时推送告警。
五、打包(Windows)
# 打包安卓APK,输出在 build/app/outputs/apk/release/
flutter build apk
iOS IPA打包:只能Mac电脑执行
flutter build ipa
六、推荐学习路线(Java团队按这个顺序学)
- Dart基础语法(1天,因为和Java很像)
- Widget基础:Text/Button/Container/Row/Column/ListView(2天)
- StatefulWidget状态管理(核心,动态告警页面)
- Http请求、Json序列化对接SpringBoot(1天)
- WebSocket实时数据流(公交告警推送)
- 项目架构分层(推荐:数据层repository / 业务逻辑 / UI层,和Spring分层思想对齐)
- 进阶:原生插件(需要蓝牙、串口、流媒体时,写Android Java插件)
状态管理入门优先:Provider,简单够用,适合企业运维APP;复杂后可换Bloc。
七、踩坑提前说(你们团队重点注意)
- Android模拟器需要开启CPU虚拟化(BIOS打开VT-x),否则跑不起来;
- 本地调试访问SpringBoot,不要写127.0.0.1,模拟器要写电脑局域网IP;
- 安卓网络权限:
AndroidManifest.xml添加INTERNET; - Dart空安全:
?可空类型,类似Java的可空判断,新手最容易报错。
八、 flutter build apk一直卡着
执行如下命令
flutter build apk --releasd --verbose
能看到console out的过程,知道错误的原因
一般有如下2个地方要改。
(1)改仓库地址
android/settings.gradle.kts
kts
pluginManagement {
val flutterSdkPath =
run {
val properties = java.util.Properties()
file("local.properties").inputStream().use { properties.load(it) }
val flutterSdkPath = properties.getProperty("flutter.sdk")
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
flutterSdkPath
}
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
//加这些内容////////////////////////////////==================================
maven("https://maven.aliyun.com/repository/google")
maven("https://maven.aliyun.com/repository/central")
maven("https://maven.aliyun.com/repository/public")
maven("https://maven.aliyun.com/repository/gradle-plugin")
/////////////////////////////==========================================
google()
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "9.1.0" apply false
id("org.jetbrains.kotlin.android") version "2.4.0" apply false
}
include(":app")
(2) 改build,不打包模拟器
android/app/build.gradle.kts
kts
plugins {
id("com.android.application")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}
android {
namespace = "com.example.flutter_application_1"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.flutter_application_1"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
// Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION
// is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)
// You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true`
// flag during build.
versionCode = flutter.versionCode
versionName = flutter.versionName
// ==========新增这一行,只打包arm64-v8a(绝大多数安卓手机)=======================================================
ndk {
abiFilters += listOf("arm64-v8a")
}
//===============================================================
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")
}
}
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
flutter {
source = "../.."
}