Read Me
- Mac环境安装很方便,跟着flutter网站走一般不会迷路,这里就不赘絮了。主要记录一些问题和开发中需要注意的地方
- 之前是iOS开发,有些基础,所以Android的问题会相对多一些,也容易犯一些简单的错误,主要还是记录给自己看,能帮到一些跟我一样没基础的人最好了
- 文章暂定分为五个部分:Read Me,常用指令,Android问题,iOS问题,Flutter问题。每个问题主要分三部分:问题描述,问题原因,解决办法
- 持续更新,发现长时间没有更新大概就是放弃的时候了吧
这里记录一些常用的指令
//诊断flutter运行需要环境
flutter docter
//清除缓存
flutter clean
//打包Android APK,这里加上--no-tree-shake-icons是加载资源时报错,下面有提到
flutter build apk --no-tree-shake-icons
Android
1.第一次失败的运行
问题描述:
➜ happy git:(dev) ✗ flutter run
Using hardware rendering with device sdk gphone x86 arm. If you notice graphics artifacts, consider enabling software rendering with "--enable-software-rendering".
Launching lib/main.dart on sdk gphone x86 arm in debug mode...
/happy/android/app/src/debug/AndroidManifest.xml:4:9-43 Error:
Attribute application@label value=(medical_management) from AndroidManifest.xml:4:9-43
is also present at [com.tencent.imsdk:imsdk-smart:5.2.210] AndroidManifest.xml:18:9-41 value=(@string/app_name).
Suggestion: add 'tools:replace="android:label"' to element at AndroidManifest.xml:3:4-40:19 to override.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:processDebugMainManifest'.
> Manifest merger failed : Attribute application@label value=(medical_management) from AndroidManifest.xml:4:9-43
is also present at [com.tencent.imsdk:imsdk-smart:5.2.210] AndroidManifest.xml:18:9-41 value=(@string/app_name).
Suggestion: add 'tools:replace="android:label"' to element at AndroidManifest.xml:3:4-40:19 to override.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 22s
问题原因:
据百度描述这个问题是项目application的label属性冲突导致,这是一个编译的常见错误,主要是AS的Gradle插件默认会启用Manifest Merger Tool,若Library项目中也定义了与主项目相同的属性(例如默认生成的android:icon和android:theme),则此时会合并失败,并报上面的错误。至于这是个什么属性,我也不是太了解,以后需要加强Android知识的学习、
解决办法:
在项目的Manifest.xml文件里的application中加入
xmlns:tools="http://schemas.android.com/tools"
tools:replace="label"
亲测有效~
2. 第一次打包报错
①问题描述:
➜ VIP-DOCTOR-NURSE-APP git:(dev) ✗ flutter build apk
Building without sound null safety
For more information see https://dart.dev/null-safety/unsound-null-safety
注: 某些输入文件使用或覆盖了已过时的 API。
注: 有关详细信息, 请使用 -Xlint:deprecation 重新编译。
注: 某些输入文件使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
This application cannot tree shake icons fonts. It has non-constant instances of IconData at the following locations:
问题原因:
百度发现是版本问题 flutter 升级最新版本 使用 treeview 打包报错
1.打包时加上 --no-tree-shake-icons
2.将flutter sdk 版本退回到稳定版本 (生产建议用 稳定版 ,。。。。。。)
②Keystore was tampered with, or password was incorrect
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:packageRelease'.
> A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
> com.android.ide.common.signing.KeytoolException: Failed to read key sign from store "/Users/ytwd/项目/VIP-DOCTOR-NURSE-APP/android/app/sign.jks": Keystore was tampered with, or password was incorrect
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
问题原因:
生成sign.jks的时候秘钥混淆了,注意这里有两个pass
解决办法:
key.properties 这个文件填写正确的信息即可
storePassword=123456
keyPassword=123456
keyAlias=sign
storeFile=sign.jks
# storeFile 签名文字
# keyAlias 文件的别名
# storepass 123456 这个是在创建签名的时候输入的 秘钥库秘钥
# keyPassword 123456 为设置的秘钥串
暂时出现上面两个问题,有问题继续更新,到这里就打包成功了
➜ VIP-DOCTOR-NURSE-APP git:(dev) ✗ flutter build apk --no-tree-shake-icons
Building without sound null safety
For more information see https://dart.dev/null-safety/unsound-null-safety
Running Gradle task 'assembleRelease'...
Running Gradle task 'assembleRelease'... Done 9.8s
✓ Built build/app/outputs/flutter-apk/app-release.apk (30.4MB).
Flutter
1. Expanded 布局最常见问题
问题描述:
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type StackParentData.
Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a Stack widget.
The ownership chain for the RenderObject that received the incompatible parent data was:
Padding ← Container ← Expanded ← Stack ← Column ← Padding ← Container ← Expanded ← Row ← Padding ← ⋯
When the exception was thrown, this was the stack
#0 RenderObjectElement._updateParentData.
package:flutter/…/widgets/framework.dart:5626
#1 RenderObjectElement._updateParentData
package:flutter/…/widgets/framework.dart:5642
#2 RenderObjectElement.attachRenderObject
package:flutter/…/widgets/framework.dart:5664
#3 RenderObjectElement.mount
package:flutter/…/widgets/framework.dart:5357
#4 SingleChildRenderObjectElement.mount
package:flutter/…/widgets/framework.dart:5973
问题原因:
错误信息已经给的比较清楚的,就是Expanded组件父试图错误
看错误代码
new Expanded(
child: new Container(
padding: EdgeInsets.only(right: 38.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Stack(
children: [
new Expanded(
child: new Container(
padding:
EdgeInsets.only(left: 15.0),
child: new Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
new Stack(
children: [
_rowMessgeView(message),
],
)
],
))),
],
)
],
))),
解决办法:
只要记住一点Expanded的上级控件一定是Column或者Row就好了
2. Flutter更新showDialog中的内容
问题描述:
在用showDialog的时候应该都遇到过这个问题,使用showDialog后,通过setState()无法更新当前dialog
问题原因:
因为dialog其实是另一个页面,准确地来说是另一个路由,因为dialog的关闭也是通过navigator来pop的,所以它的地位跟你当前主页面一样。这个概念一定要明确,因为无论在Android或iOS中,daliog都是依附于当前主页面的一个控件,但是在Flutter中不同,它是一个新的路由。所以使用当前主页面的setState()来更新,当然没法达到你要的效果。
解决办法:
所以我们有两种方法来解决这个问题,一种是使用StatefulBuilder,另一种是使用自定义的StatefulWidget。
这里只用StatefulBuilder,代码如下:
showDialog(
context: context,
builder: (context) {
String label = 'test';
return StatefulBuilder(
builder: (context, state) {
print('label = $label');
return GestureDetector(
child: Text(label),
onTap: () {
label = 'test8';
print('onTap:label = $label');
// 注意不是调用老页面的setState,而是要调用builder中的setState。
//在这里为了区分,在构建builder的时候将setState方法命名为了state。
state(() {});
},
);
},
);
});
//这里直接调用state(() {}) 代替setState(() {})
3. Flutter动画生命周期问题
问题描述:
Unhandled Exception: _ChatViewPageState#1e2cd(tickers: tracking 1 ticker) was disposed with an active Ticker.
_ChatViewPageState created a Ticker via its TickerProviderStateMixin, but at the time dispose() was called on the mixin, that Ticker was still active. All Tickers must be disposed before calling super.dispose().
Tickers used by AnimationControllers should be disposed by calling dispose() on the AnimationController itself. Otherwise, the ticker will leak.
The offending ticker was:
_WidgetTicker(created by _ChatViewPageState#1e2cd(lifecycle state: created, tickers: tracking 0 tickers))
The stack trace when the _WidgetTicker was actually created was:
#0 new Ticker.
package:flutter/…/scheduler/ticker.dart:67
#1 new Ticker
package:flutter/…/scheduler/ticker.dart:69
#2 new _WidgetTicker
package:flutter/…/widgets/ticker_provider.dart:271
#3 TickerProviderStateMixin.createTicker (package:flutter/s<…>
4. Flutter组件Image
问题描述:
- 不能识别iOS多倍图。
Image.asset(
'assets/images/[email protected]',
scale: 3,
width: 24,
height: 24,
)
5. Flutter切换tabbar时,首次切换图片闪烁
解决方式:gaplessPlayback参数设置true
Image.asset(
e.selectImage,
scale: 3,
color: e.selectColor,
excludeFromSemantics: true,
gaplessPlayback: true,
)