1.输入法导致的null--StatefulWidget状态丢失了
- 背景:
在一个页面中有TextField和一个Wrap,其中Wrap是包含了一个不定数量的List<Image> list,该页面是某个页面push进来的,传入的list可能为null,也可能不为null,为null的时候在initState创建了一个空的List,问题在于,当点击TextField弹起输入法时,导致Wrap中的照片全部丢失了。
如果StatefulWidget是上一个页面创建的,输入法弹起会导致页面重建,上个页面传入的参数重置,从而导致意外发生
- 原因分析:
输入法的弹出和消失导致了StatefulWidget.didUpdateWidget、StatefulWidget.build两个方法的执行,其中在didUpdateWidget时丢失了部分状态,特别时在initState方法中初始化的状态会丢失,导致页面的build时发生意外。 - 解决:
overridedidUpdateWidget方法,把需要保存的状态值,重新赋值给新的Widget。
未覆写didUpdateWidget

- 扩展:有可能在其他情况也会导致didUpdateWidget方法的执行,导致Widget重新创建,所有如果你的StatefulWidget中的某些状态是需要在
initState方法中创建的,那么你就覆写didUpdateWidget方法,从而保留你需要的值。
StatefulWidget 生命周期(盗图...)
2.输入法弹出又自动消失?
背景
由于使用了Provider管理状态,所有界面均为StatelessWidget。登录界面的Form表单设置了final GlobalKey<FormState> loginKey = GlobalKey();,如果这个key定义在Widget内部,当点击TextFormFiled时弹出输入法,会导致该StatelessWidget重构,并使得输入法自动消失。建议定义在全局变量,以避免错误发生。
//正确定义位置
final GlobalKey<FormState> loginKey = GlobalKey();
class LoginPage extends StatelessWidget {
//导致错误的写法
// final GlobalKey<FormState> loginKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Form(
key:loginKey
);
}
}
3.输入法消失导致TextFormFiled文本自动消失?
背景如2,由于输入法的弹出与消失导致
StatelessWidget重构,所以要保证所用的TextEditingController不发生变化。修改方法就是将TextEditingController定义在全局或者传递进来TextEditingController并保证在TextEditingController重构时不变化
4.在Column中嵌套一个ListView
由于ListView的高度或者宽度是无限的,导致布局错误,从而
Widget的丢失,黑屏或者Widget不可见。一个解决办法就是把ListView嵌入Expanded.
5.run或build时卡Gradle的
可能是墙了,按照网上说的,配置Flutter SDK中的
..SdkDir\packages\flutter_tools\gradle\flutter.gradle和工程下的../android/build.gradle中的maven配置
// google() 改为
maven { url 'https://maven.aliyun.com/repository/google' }
// jcenter() 改为
maven { url 'https://maven.aliyun.com/repository/jcenter' }
具体url 可以查看阿里Maven
对于新配置的环境,另外一种可能是
Flutter SDK与Android SDK version不对应。
cmd 下执行 flutter doctor 查看'Android SDK version'
Flutter version 1.12.13+hotfix.7 要求Android 28,首次运行时,高于该版本无错误报告并卡住,低于该版本报错
6.Flutter SDK 降级方法
7.可滚动的 ExpansionTile
Flutter原生的
ExpansionTile,展开的是一个Column,如果子列表项太多,则会导致溢出,且不可上下滚动。
改造,复制所有ExpansionTile代码,修改其中的build方法:
@override
Widget build(BuildContext context) {
final bool closed = !_isExpanded && _controller.isDismissed;
return LayoutBuilder(
builder: (c, con) {
//通过LayoutBudilder获取父布局对大小的限制
return AnimatedBuilder(
animation: _controller.view,
builder: _buildChildren,
child: closed
? null
: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: con.biggest.width,
maxHeight: con.biggest.height - 58 //减掉title的高度,一般是58
),
child: ListView(
children: widget.children,
),
),
);
},
);
}

