我有一个使用FutureBuilder显示信息的应用程序。
当我打开Textfield时,出现软键盘,并重新创建FutureBuilder的状态。有什么方法可以避免不必要地运行build方法。
显然,当我使用init状态调用future时,它可以工作,但对于其他功能(如删除数据),则不起作用,因为future只被调用一次。
这是我的代码
class FutureBuilderWidget extends StatefulWidget {
@override
_FutureBuilderWidgetState createState() => _FutureBuilderWidgetState();
}
class _FutureBuilderWidgetState extends State<FutureBuilderWidget> {
final _appBar = AppBar();
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Provider.of<QuickNotesProvider>(context, listen: false)
.fetchAndSetNotes(),
builder: (ctx, snapshot) {
return snapshot.connectionState == ConnectionState.waiting
? Center(
child: Text('loading...'),
)
: Consumer<QuickNotesProvider>(
child: Center(
child: Container(
margin: EdgeInsets.only(
top: MediaQuery.of(context).size.height * 0.3),
child: Column(
children: <Widget>[
Icon(Icons.calendar_today,
size: MediaQuery.of(context).size.height *
0.07),
SizedBox(
height: 6,
),
Text('Added Notes will appear here',
style:
Theme.of(context).textTheme.headline),
SizedBox(
height: 10,
),
Text(
'Tap + to add a quick note',
style: TextStyle(
fontSize:
MediaQuery.of(context).size.height *
0.02,
fontWeight: FontWeight.w400),
)
],
),
),
),
builder: (ctx, eventData, ch) {
if (eventData.quicknotes.length == 0) {
return ch;
} else {
return Container(
height: (MediaQuery.of(context).size.height -
_appBar.preferredSize.height -
MediaQuery.of(context).padding.top -
MediaQuery.of(context).padding.bottom) *
0.869,
child: ListView.builder(
itemCount: eventData.quicknotes.length,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.only(
left: 10, top: 7, right: 10),
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(5)),
color: Color.fromRGBO(230, 230, 230, 1),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(
top: 10, left: 8),
child: Text(
eventData.quicknotes[index]
.quicknote,
),
),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: <Widget>[
Padding(
padding:
const EdgeInsets.only(
right: 10.0),
child: InkWell(
onTap: () {
setState(() {
eventData.deleteEvents(
eventData
.quicknotes[
index]
.id);
});
},
child: Icon(
Icons.more_horiz,
color: Colors.black54,
),
),
)
],
)
],
),
));
},
),
);
}
});
},
);
}
}
答案 0 :(得分:0)
那是正常的。当软键盘出现时,您的布局便会调整大小,因此会重新构建。
您可以通过在小部件的resizeToAvoidBottomInsets
祖先中设置Scaffold
来避免调整大小,但是如果发生任何重建,问题将自行解决。
一种解决方法是将Future
结果缓存。
我相信您可以使用Completer来阻止重新执行。
在您的State
中创建
var myCompleter = Completer<YourDataDype>()
然后在initState
中启动您的future函数,但不要返回结果,而是这样做:
myCompleter.complete(yourData)
然后您可以将myCompleter.future
传递到FutureBuilder
并查看会发生什么情况。
就我个人而言,我从来没有做过此事,因为我使用BLoC pattern将逻辑和演示分开了,但是它确实适合您的情况。
您也应该开始拆分逻辑,因为这将避免很多麻烦并提高代码库质量!