| 项目 | 要求 |
|---|---|
| Flutter | ^3.10.0(建议 3.10.x stable,如 3.10.6) |
| Dart SDK | >=3.0.0 <4.0.0 |
| Java | 17(项目已配置为 Java 17,与 AGP 8.x 一致) |
| Android Gradle Plugin (AGP) | 8.2.2 |
| Gradle | 8.7 |
| Kotlin | 1.9.22 |
| compileSdkVersion | 34 |
| minSdkVersion | 23 |
| targetSdkVersion | 34 |
项目中配置了 org.gradle.java.home,用于指定本工程 Android 构建时使用的 JDK 路径。这样做的原因:
- 与系统 JDK 解耦:本机可能装有多套 JDK(如 8、11、17),默认
JAVA_HOME或java可能指向其它版本。Gradle 会优先使用org.gradle.java.home,确保执行 Gradle、AGP、Kotlin 编译时统一用 Java 17,避免因版本不一致导致的构建失败。 - 满足 AGP 8.x 要求:Android Gradle Plugin 8.x 要求 Java 17,显式指定可避免误用 Java 11 等旧版本。
- 团队协作:该路径是本机路径(如
/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home),其他人拉代码后若 JDK 安装位置不同,需要改成自己机器上的 JDK 17 路径,或删除/注释该行,改用环境变量JAVA_HOME。
若你使用 Java 17 且已设置 JAVA_HOME,也可以不配置 org.gradle.java.home,Gradle 会使用 JAVA_HOME。
项目当前使用 Java 17。若你本机使用不同 Java 版本,可按以下方式配置:
-
使用 Java 17(推荐,与项目一致)
- 安装 JDK 17(如 Zulu OpenJDK 17 或 Oracle JDK 17)。
- 设置环境变量(以 macOS/Linux 为例):
export JAVA_HOME=/path/to/jdk-17 # 替换为你的 JDK 17 路径 export PATH="$JAVA_HOME/bin:$PATH"
- 验证:
java -version应显示 17.x。
-
修改项目以使用其他 Java 版本(如 Java 11 或 21)
- 编辑
android/app/build.gradle:android { compileOptions { sourceCompatibility JavaVersion.VERSION_17 // 改为 VERSION_11 或 VERSION_21 targetCompatibility JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = '17' // 改为 '11' 或 '21' } }
- 若
android/gradle.properties里配置了org.gradle.java.home,需改为目标 JDK 的安装路径,或删除该行改用环境变量。 - 注意:AGP 8.x 官方要求 Java 17,若降级到 Java 11 需同时降级 AGP(如改为 7.x),在
android/settings.gradle中修改com.android.application版本并对应调整 Gradle 版本。
- 编辑
-
多版本 Java 共存(如通过 asdf、jenv、sdkman)
- 在项目目录下使用对应工具切换到 JDK 17,例如:
# jenv 示例 jenv local 17 # 或 asdf asdf local java openjdk-17.0.x
- 确保
JAVA_HOME与java -version一致。
- 在项目目录下使用对应工具切换到 JDK 17,例如:
| 项目 | 要求 |
|---|---|
| 操作系统 | macOS(仅 macOS 可编译 iOS 应用) |
| Xcode | 最新稳定版或与 Flutter 3.10 兼容的版本(建议 14.x 或 15.x) |
| CocoaPods | 已安装(gem install cocoapods 或 brew install cocoapods) |
| iOS 最低部署版本 | 12.0 |
| Swift | 5.0 |
cd ios && pod install && cd ..
flutter run若遇到 CocoaPods 或 Xcode 签名问题,请确保:
- 已用 Xcode 打开过
ios/Runner.xcworkspace并选择开发团队(Signing & Capabilities)。 - 模拟器或真机的系统版本 ≥ iOS 12.0。
# Flutter
Flutter 3.10.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision f468f3366c (9 months ago) • 2023-07-12 15:19:05 -0700
Engine • revision cdbeda788a
Tools • Dart 3.0.6 • DevTools 2.23.1
# Java(建议与项目一致使用 17)
openjdk version "17.x.x" ...flutter build apk --release --target-platform android-arm64,android-arm项目已做以下优化以减小 release APK 体积:
- 资源:仅打包运行时需要的资源(
assets/icons/、assets/images/、network_image.json、city_list.json),不包含assets/preview/等文档用资源。 - Android:已开启 R8 代码压缩与资源收缩(
minifyEnabled true、shrinkResources true),规则见android/app/proguard-rules.pro。
如需进一步减小体积,可:
- Dart 混淆并剥离调试信息(发布时建议):
flutter build apk --release --obfuscate --split-debug-info=./debug-info/
- 上架 Google Play 时使用 App Bundle(按设备生成更小 APK):
flutter build appbundle --release --obfuscate --split-debug-info=./debug-info/
flutter drive --target=test_driver/app.dart# 普通 release
flutter build apk --release
# 体积优化(混淆 + 剥离调试信息)
flutter build apk --release --obfuscate --split-debug-info=./debug-info/flutter run --profile --trace-skia
flutter screenshot --type=skia --observatory-uri=http://127.0.0.1:49368/s4vbW7Mp_KE=/#/timelineFlutter 中,RouteAware 是一个 widget mixin,用于监听路由的推送和弹出事件。这使得 widget 能够知道它们何时被显示或隐藏,例如当用户导航到一个页面或从一个页面返回时。这对于跟踪页面视图或执行在页面进入或离开屏幕时的操作特别有用。
RouteAware 需要和 RouteObserver 一起使用,后者是一个监听 Navigator 路由堆栈变化的类。你需要在全局范围内创建一个 RouteObserver 并在整个应用中使用它,这样 RouteAware mixin 的 widgets 才能注册到观察者并接收路由变化的通知。
class _NewViewState extends State<NewView> with RouteAware {
@override
void didChangeDependencies() {
super.didChangeDependencies();
App.routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute<dynamic>);
debugPrint("$this");
}
@override
void didPopNext() {
// Covering route was popped off the navigator.
debugPrint('返回NewView');
}
@override
void didPush() {
// Route was pushed onto navigator and is now topmost route.
debugPrint('进入NewView');
}
@override
void dispose() {
App.routeObserver.unsubscribe(this);
super.dispose();
}
}Navigator.of(context).pushNamed 直接进入新页面(每次都将新建一个新的页面)
Navigator.of(context).pushReplacementNamed把当前页面在栈中的位置替换成跳转的页面(替换导航器的当前路由,通过推送路由[routeName]),当新的页面进入后,之前的页面将执行dispose方法
Navigator.of(context).popAndPushNamed将当前页面pop,然后跳转到制定页面(将当前路由弹出导航器,并将命名路由推到它的位置
Navigator.of(context).pushNamedAndRemoveUntil将制定的页面加入到路由中,然后将其他所有的页面全部pop, (Route route) => false将确保删除推送路线之前的所有路线。 这时候将打开一个新页面
例如 当用户点击了退出登录时,我们需要进入某一个页面(比如点退出登录后进入了登录页),这个时候用户点击返回时不应该能进入任何一个页面,这种情况就可以使用
Navigator.of(context).pushNamedAndRemoveUntil('/', (Route<dynamic> route) => false);
Navigator.of(context).pushNamedAndRemoveUntil将指定的页面加入到路由中,然后将之前的路径移除直到指定的页面为止(将具有给定名称的路由推到导航器上,然后删除所有路径前面的路由直到'predicate'返回true为止。) 这时候将销毁栈内除了screen4的页面,点击直接去栈内screen4,这时screen4会重新build
Navigator.of(context).pushNamedAndRemoveUntil('/screen4', ModalRoute.withName('/screen1'));Navigator.of(context).popUntil推出之前push的路由直到/newView路由为止
Navigator.of(context).popUntil(ModalRoute.withName('/newView')) Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (BuildContext context) => new screen4()),
ModalRoute.withName('/'), Navigator.popUntil(context, ModalRoute.withName('/screen2'));UrlConfig.of().urlclass CustomBehavior extends ScrollBehavior {
@override
Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) {
return child;
}
}
ScrollConfiguration(
behavior: CustomBehavior(),
child: ListView.builder(
itemCount: 60,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 44.0,
width: MediaQuery.of(context).size.width,
child: Center(child: Text('Data-$index')),
);
},
),
)final bool isDark = Theme.of(context).brightness == Brightness.dark;CustomColors.of(context).borderColormaybePop 会自动进行判断,如果当前页面pop后,会显示其他页面,不会出现问题,则将执行当前页面的pop操作 否则将不执行
Navigator.of(context, rootNavigator: true).maybePop();











