iOS 调试
真机调试
-
Xcode run 在控制台获取 Dart VM service URI
-
VSCode 点击
Cmd + Shift + P选择 Debug: Attach to Flutter on Device -
粘贴 the URI 后点击 Enter
官方文档: 在混合开发模式下进行调试
常见问题:Exception attempting to connect to the VM Service: SocketException: Connection refused
flutter devices
flutter attach -d <deviceId>
inspector
- VSCode 点击
Cmd + Shift + P选择 Dart: Open DevTools in Browser - select widget mode
通用地图
状态管理
Consumer
- 监听
Provider提供的数据,当在应用的某个地方使用Provider 来暴露一个数据模型时,你可以在widget树的任何其他地方使用 Consumer 来读取并响应这个数据模型的变化。 - 当 Provider 中的数据发生变化时,Consumer 会自动重建其子widget,这样就可以根据新的数据状态更新UI。
Provider 数据更新后页面未刷新
- 没有调用 notifyListeners()
- context 不同 页面若取的是当前页面的 context 而不是管理 Provider 数据页面的 context 那无法拿到 Provider 数据
- 没有触发 set 方法 在方法中更新私有变量时直接调用的下划线方法 _unreadNum 而不是通过它的 setter 方法来更新的
- 没有改变引用
- Selector 监听的是 messageList 的引用变化。如果只是对列表进行操作,如 add 而不更新列表的引用,Selector 不会检测到变化。
- 直接赋值,例如 List<MessageDetailModel?> newMessageList = messageList; 赋值没有真正改变其值,在这种情况下,shouldRebuild 函数会返回 false。应该使用 List<MessageDetailModel?> newMessageList = List.from(messageList);
异步
Group
Future<void>? _sendInfoFuture;
Future<void>? _receiptInfoFuture;
@override
void onSuccessCallBack(BaseResponse? response, String tag) {
if (tag == xxx) {
_sendInfoFuture = Future.value();
} else if (tag == xxx) {
_receiptInfoFuture = Future.value();
}
// 优化请求都成功后再更新数据
if (_sendInfoFuture != null && _receiptInfoFuture != null) {
Future.wait([_sendInfoFuture!, _receiptInfoFuture!]).then((_) {
changeCount(sendNumber: sendList?.packageNum, receiveNumber: receiveList?.packageNum);
notifyListeners();
});
}
}
原生交互
// 原生代码
FlutterMethodChannel *pushInitChannel = [FlutterMethodChannel methodChannelWithName:@"jd.logistic.pushInitChannel" binaryMessenger:controller.binaryMessenger];
[pushInitChannel invokeMethod:@"saveNotification" arguments:jsonString];
// flutter 代码
MethodChannel pushInitChannel = MethodChannel('jd.logistic.pushInitChannel');
pushInitChannel.setMethodCallHandler(_handleNativeMethod);
Future<void> _handleNativeMethod(MethodCall call) async {
switch (call.method) {
case 'saveNotification':
String data = call.arguments;
saveMessageToDatabase(data);
break;
default:
print("Unknown method called");
}
}
国际化
VSCode 安装 flutter Intl 插件
特殊 UI
自动计算高度
GridView shrinkWrap
GridView 的 shrinkWrap 属性决定了是否根据子组件的总长度来调整 GridView 的长度。当 shrinkWrap 设置为 true 时,GridView 会占用其子组件所需要的最小空间,而不是扩展到尽可能大的空间。这在将 GridView 嵌入到无法提供无限空间的组件(如 ListView 或者 Column)中时非常有用,因为它可以防止 GridView 占用更多的空间,导致渲染异常。然而,使用 shrinkWrap 可能会增加性能开销,因为它需要计算子组件的总长度。
GridView.builder(
shrinkWrap: true,
)
AnimatedSize
Consumer<PackageTabWidgetViewModel>(builder: (BuildContext context, value, Widget? child) {
return AnimatedSize(
duration: Duration(milliseconds: 50),
curve: Curves.easeInOut,
child: value.model.selectedIndex == 0
? ReceivePackageList()
: SendPackageList(),
);
})
常见问题
- 新增本地图片后加载时报错 Unable to load asset
- 执行 clean.sh 和 get.sh 脚本
- 检查
pubspec.yaml文件
- Command PhaseScriptExecution failed with a nonzero exit code
清除 Flutter 应用的本地缓存 flutter pub cache clean
- 执行 flutter doctor 后报错 Xcode installation is incomplete [!] Xcode - develop for iOS and macOS ✗ Xcode installation is incomplete
# 确保 Xcode 已正确配置
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch
- [Flutter 运行IOS真机,提示无法打开“iproxy”]
在终端输入命令行 sudo xattr -d com.apple.quarantine ${flutter SDK iproxy 路径}
如:sudo xattr -d com.apple.quarantine /Users/xxx/Library/Developer/flutter/bin/cache/artifacts/usbmuxd/iproxy
(blog.csdn.net/hzqit520/ar…)
- Target of URI doesn't exist: 'package:xxx_image.dart'. Try creating the file referenced by the URI, or Try using a URI for a file that does exist.
执行 Flutter: Clean Project
- jaguar_serializer 数据解析报错
flutter packages pub run build\_runner build --delete-conflicting-outputs --verbose 注意在对应的 package 目录执行指令
官网文档 pub.dev/packages/ja…