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

查看:1090
本文介绍了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);
}

如果有更好的方法进行此检查,并在需要时调用模式,请为我指出正确的方向,我在寻找 onState onRender 函数,或者我可以分配的回调函数到要在渲染上调用的 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重定向到initState上的页面

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:


您不能使用<$ c
方法中的$ c> [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.

一种简单的方法

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函数中使用异步调用的一些技巧: / p>

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天全站免登陆