Flutter 在 initState 方法中获取上下文 [英] Flutter get context in initState method

查看:39
本文介绍了Flutter 在 initState 方法中获取上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定 initState 是否适合于此功能.我想要实现的是检查页面何时呈现以执行一些检查,并根据它们打开 AlertDialog 以在需要时进行一些设置.

I'm not sure if the initState is the right function for this. What I'm trying to achieve is to check when the page is rendered to perform some checks and based on them opening a AlertDialog to make some settings if needed.

我有一个有状态的页面.它的 initState 函数看起来像这样:

I've got a Page which has a state. It's initState function looks like this:

@override
void initState() {
    super.initState();
    if (!_checkConfiguration()) {
        _showConfiguration(context);
    }
}

_showConfiguration 像这样:

void _showConfiguration(BuildContext context) {
    AlertDialog dialog = new AlertDialog(
        content: new Column(
            children: <Widget>[
                new Text('@todo')
            ],
        ),
        actions: <Widget>[
            new FlatButton(onPressed: (){
                Navigator.pop(context);
            }, child: new Text('OK')),
        ],
    );

    showDialog(context: context, child: dialog);
}

如果有更好的方法进行此检查,并且需要调用模态,请指出正确的方向,我正在寻找 onStateonRender 函数,或者我可以分配给 build 函数以在渲染时调用但无法找到的回调.

If there's a better way to make this checks and if needed call the modal, please point me in the proper direction, I was looking for a onState or onRender function, or a callback I could assign to the build function to be called on render but wasn't able to find one.

在这里接缝他们有一个类似的问题:Flutter Redirect toinitState 上的一个页面

It seams over here they had a similar problem: Flutter Redirect to a page on initState

推荐答案

成员变量上下文可以在 initState 期间访问,但不能用于所有情况.这是来自 initState 文档的颤振:

The member variable context can be accessed during initState but can't be used for everything. This is from the flutter for initState documentation:

您不能从这里使用 [BuildContext.inheritFromWidgetOfExactType]方法.但是,[didChangeDependencies] 会被立即调用遵循此方法,并且 [BuildContext.inheritFromWidgetOfExactType]可以在那里使用.

You cannot use [BuildContext.inheritFromWidgetOfExactType] from this method. However, [didChangeDependencies] will be called immediately following this method, and [BuildContext.inheritFromWidgetOfExactType] can be used there.

您可以将初始化逻辑移至 didChangeDependencies,但这可能不是您想要的,因为 didChangeDependencies 可以在小部件的生命周期中多次调用.

You could move your initialization logic to didChangeDependencies, however that might not be exactly what you want as didChangeDependencies can be called multiple times in the lifecycle of the widget.

如果您改为进行异步调用,在小部件初始化之前委托您的调用,则您可以按照自己的意愿使用上下文.

If you instead make an asynchronous call which delegates your call until after the widget has been initialized, you can then use context as you intend.

一个简单的方法是使用未来.

A simple way to do that is to use a future.

Future.delayed(Duration.zero,() {
  ... showDialog(context, ....)
}

另一种可能更正确"的方法是使用 flutter 的调度器添加帧后回调:

Another way, which may be more 'correct', is to use flutter's scheduler to add a post-frame callback:

SchedulerBinding.instance.addPostFrameCallback((_) {
  ... showDialog(context, ....)
});

最后,这里有一个我喜欢在 initState 函数中使用异步调用的小技巧:

And finally, here's a little trick I like to do to use asynchronous calls in the initState function:

() async {
  await Future.delayed(Duration.zero);
  ... showDialog(context, ...)      
}();

这是一个使用简单 Future.delayed 的完整示例:

Here's a fully fleshed out example using the simple Future.delayed:

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  bool _checkConfiguration() => true;

  void initState() {
    super.initState();
    if (_checkConfiguration()) {
      Future.delayed(Duration.zero,() {
        showDialog(context: context, builder: (context) => AlertDialog(
          content: Column(
            children: <Widget>[
              Text('@todo')
            ],
          ),
          actions: <Widget>[
            FlatButton(onPressed: (){
              Navigator.pop(context);
            }, child: Text('OK')),
          ],
        ));
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }
}

<小时>

通过评论中提供的来自 OP 的更多上下文,我可以为他们的特定问题提供更好的解决方案.根据应用程序的不同,您实际上可能希望根据是否是第一次打开应用程序来决定显示哪个页面,即将 home 设置为不同的内容.对话框不一定是移动设备上最好的 UI 元素;最好显示包含他们需要添加的设置和下一步按钮的完整页面.


With more context from the OP provided in comments, I can give a slightly better solution to their specific problem. Depending on the app, you may actually want to make a decision based on which page to show depending on whether it's the first time the app is opened i.e. set home to something different. And dialogs aren't necessarily the best UI element on mobile; it may be better to show a full page with the settings they need to add and a next button.

这篇关于Flutter 在 initState 方法中获取上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆