如何为小部件实现标准行为

时间:2019-04-11 11:19:40

标签: dart flutter dialog loading code-design

我想解决以下情况:

一个屏幕/小部件正在显示(按下)。 该屏幕需要:

  • 在首次创建时执行一项长任务(请求)
  • 在执行任务(要求)时显示负载
  • 根据需要显示错误对话框(请求失败)
  • 任务完成后相应地更新列表
  • 具有外部触发器来更新和重新启动长任务(再次请求数据+包括加载和警报)

——————————————————————————

我得出的结论是,如果没有以下内容,您将无法拥有这种行为:

  • 显示错误对话框的延迟机制(addPostFrameCallback或Future.delayed)
  • 用于处理组件行为(初始/ 加载 /非加载/完成)的状态机制

要提及的是,flutter对我来说是新事物,我可能会缺少有关该框架的重要信息。

——————————————————————————

这是上述结论的原因。

错误对话框限制:

  • 在build方法中,您无法显示对话框,因为您需要先返回小部件(例如,任务失败,则需要显示对话框);否则会提示错误

// ... // flutter:在构建期间调用setState()或markNeedsBuild()。 // flutter:此Overlay小部件不能标记为需要构建,因为该框架已经在 // setState()或markNeedstoBuild() //...

  • 如果在生成方法之前执行任务,但失败,您将再次遇到相同的错误 // ... // flutter:在之前调用了InheritedFromWidgetOfExactType(_LocalizationsScope)或inheritFromElement() //颤振:_VacationsViewState.initState()已完成。 //...

  • 该构建方法无法触发任务,因为该方法被调用了很多次。

状态指示器限制:

  • 在构建窗口小部件组件之后,如果任务再次触发执行,则除非具有此状态机制,否则该组件将无法知道需要显示加载指示符。这种状态机制意味着调用setState或使用streambuilders(基于状态)。

——————————————————————————

其他片段来举例说明这些情况:

// using FutureBuilder
Widget build(BuildContext context) {
    return FutureBuilder(
    future: someFuture,
    builder: (BuildContext context, AsyncSnapshot snapshot) {
        // Here we need to display loading while task is not finished and a dialog if it fails
        // dialog needs to be performed with a delay
        // triggering again the build will need to have a setState called to “reload”
    });
}

// using StreamBuilder
Widget build(BuildContext context) {
    return StreamBuilder<void>(
        stream: status,
        builder: (BuildContext context, AsyncSnapshot<void> status) {
           //  status can represent states (loading/finished/… )
       // dialog needs to be displayed with a delay in case the error the current state
    });
}

——————————————————————————

达成最终妥协:

  • 使用带有状态描述符和可能的流的某种状态机制,或直接使用setState
  • 使用对话框延迟机制

——————————————————————————

1 个答案:

答案 0 :(得分:0)

我实际上无法尝试,但是这种解决方法不能解决您的问题吗?

使用setState有什么问题?

Future _calculation;

initState(){
  super.initState();
  _calculation = fetchData();
}


  FutureBuilder<String>(
  future: _calculation, // a previously-obtained Future<String> or null
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return Text('Press button to start.');
      case ConnectionState.active:
      case ConnectionState.waiting:
        return Text('Awaiting result...');
      case ConnectionState.done:
        if (snapshot.hasError)
          //show your error dialog

          // show result
        return Text('Result: ${snapshot.data}');
    }
    return null; // unreachable
  },
);

  new RaisedButton(
  child: const Text('Reload'),
  color: Theme.of(context).accentColor,
  elevation: 4.0,
  splashColor: Colors.blueGrey,
  onPressed: () {
    setState((
      // this will trigger the FutureBuilder and update/show the result
      _calculation = fetchData();
    ));
  },
),