如何在从后端API等待数据时初始显示RefreshIndicator?

Iir*_*kka 9 flutter

所以,我有这个"通知"屏幕,显示用户的通知.当导航到此屏幕时,它将变为空白,因为通知是从后端API实时加载的.

这里有一些代码来说明问题:

class _MyItemsPageState extends State<MyItemsPage> {
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
      new GlobalKey<RefreshIndicatorState>();
  List<MyItem> _items = [];

  @override
  void initState() {
    super.initState();

    // Nothing is displaying on screen initially, since the items are loaded from API on startup.
    // Preferably in this state, the refresh indicator would be shown while the items load.
    // It's not currently possible in this place, since it seems that the Widget hasn't been built yet.

    _refreshIndicatorKey.currentState.show(); // currentState null at this time, so the app crashes.
    _loadItems();
  }

  // (unrelated code removed)

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new RefreshIndicator(
        key: _refreshIndicatorKey,
        onRefresh: _loadItems,
        child: new ListView(
          padding: new EdgeInsets.symmetric(vertical: 8.0),
          children: _buildItemWidgets(),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是,当调用initState()函数时,_refreshIndicator.currentState为null ,因为尚未构建Widget.

在这种情况下,在RefreshIndicator上调用show()的适当位置是什么?

小智 8

我认为最好的选择是_refreshIndicatorKey.currentState.show()使用https://docs.flutter.io/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html 这样当小部件完成构建时可以安全地调用 show() 方法,并且不依赖于未来的固定时间。

这里的例子:

void initState() {
    super.initState();
    SchedulerBinding.instance.addPostFrameCallback((_){  _refreshIndicatorKey.currentState?.show(); } );
  }
Run Code Online (Sandbox Code Playgroud)

但是,当然,我确实认为小部件本身可以有一个额外的参数来允许开箱即用。

  • 绝对应该是小部件中的单独参数。 (4认同)

Iir*_*kka 6

事实证明,把_refreshIndicator.currentState.show()我的_loadItems()功能放在里面就可以了.所以类似于:

Future _loadItems() async { 
    _refreshIndicatorKey.currentState?.show(); 
    var items = await getItems();

    setState(() { 
        _items = items; 
    });
}
Run Code Online (Sandbox Code Playgroud)

然后我_loadItems()initState()方法中像往常一样调用函数,但从_refreshIndicatorKey.currentState.show()那里删除了行.

我认为这只是因为async loadItems函数的性质导致一些可能的竞争条件,并且感觉应该有一些与小部件状态的生命周期相关的其他解决方案.