TransWikia.com

AlertDialog как правильно использовать Navigator.of(context).pop()?

Stack Overflow на русском Asked on December 28, 2021

Пояснение, что делает приложение. Происходит нажатие на кнопку Show. Появляется диалоговое окно. Если в нем нажать Ok, появляется текст, название кнопки изменятся на Hide, если нажать Cancel, то текст не появляется, название кнопки остается прежним. Если нажать на Hide, текст исчезает. Все просто.

Дальше будет полный приведен код. Все работает.

Что мне не понятно. Если в код поместить вызов функции, все нормально работает

Navigator.of(context).pop( _f2() );

Если поместить реализацию этой функции, происходит ошибка, подчеркнута первая точка с запятой

Navigator.of(context).pop(
 _b = true;
 _visible = true;
 _text = 'Hide';
);

Если поместить реализацию этой функции в setState ошибки не происходит, работает нормально

Navigator.of(context).pop(
 setState(() {
   _b = true;
   _visible = true;
   _text = 'Hide';
  })
);

Если поместить анонимную функцию, ошибки нет, но текст не появляется

Navigator.of(context).pop(
 () {
   _b = true;
   _visible = true;
   _text = 'Hide';
 }
);

Все дело в setState ?
Подскажите, как вообще правильно сделать? Спасибо.

Вот полный код.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return MaterialApp(
   debugShowCheckedModeBanner: false,
   title: 'Name App',
   theme: ThemeData(
    primarySwatch: Colors.blue,
   ),
   home: Scaffold(
    appBar: AppBar(
     title: Text('Name Page'),
    ),
    body: MyHomePage(),
   ),
  );
 }
}

class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

 String _text;
 bool _visible;
 bool _b;

 @override
 void initState() {
  super.initState();
  _text = 'Show';
  _visible = false;
  _b = false;
 }

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

 }

 void _f1() {
  setState(() {
   switch(_b) {
    case false:
     _showAlertDialog1();
     break;
    case true:
     _b = false;
     _visible = false;
     _text = 'Show';
     break;
   }
  });
 }

 void _f2() {
  setState(() {
   _b = true;
   _visible = true;
   _text = 'Hide';
  });
 }

 Future<void> _showAlertDialog1() async {
  return showDialog<void>(
   context: context,
   barrierDismissible: false,
   builder: (BuildContext context) {
    return AlertDialog(
     title: Text(
      'SHOW TEXT!'
     ),
     content: Text(
      'Show text now'
     ),
     actions: <Widget>[
      FlatButton(
       onPressed: () {

        //все нормально работает
        Navigator.of(context).pop( _f2() );

        //происходит ошибка, подчеркнута первая точка с запятой
        /*Navigator.of(context).pop(
         _b = true;
         _visible = true;
         _text = 'Hide';
        );*/

        //ошибки не происходит, работает нормально
        /*Navigator.of(context).pop(
         setState(() {
          _b = true;
          _visible = true;
          _text = 'Hide';
         })
        );*/

        //ошибки нет, но текст не появляется
        /*Navigator.of(context).pop(
         () {
          _b = true;
          _visible = true;
          _text = 'Hide';
         }
        );*/

       },
       child: Text(
        'Ok',
       ),
      ),
      FlatButton(
       onPressed: () {
        Navigator.of(context).pop();
       },
       child: Text(
        'Cancel',
       ),
      ),
     ],
    );
   }
  );
 }

 @override
 Widget build(BuildContext context) {
  return Stack(
   children: <Widget>[
    Align(
     alignment: Alignment.topLeft,
     child: Container(
      width: double.infinity,
      margin: const EdgeInsets.all(16.0),
      child: RaisedButton(
       onPressed: () { _f1(); },
       splashColor: Colors.blue.withOpacity(0.5),
       shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(10)
       ),
       child: Text(
        _text,
        style: TextStyle(
         color: Colors.deepPurple,
         fontSize: 20.0,
        ),
       ),
      ),
     ),
    ),
    Align(
     alignment: Alignment.center,
     child: Visibility(
      visible: _visible,
      child: Text(
       'Hello World!',
       style: TextStyle(
        color: Colors.pink,
        fontSize: 36.0,
       ),
      ),
     ),
    ),
   ],
  );
 }

}

One Answer

Для начало надо посмотреть что из себя представляет setState:

void setState(void Function() fn)

А теперь из чего состоит (){} (анонимная функция):

void Function() // более подробно: void *без названия*(){}

А теперь вопрос: заметили сходства между setState и (){}?

Ответ: это обе void функции.


А теперь к Navigator.of(context).pop(), посмотри из чего состоит pop:

void pop<T extends Object>([T result])

T (т.е. дженерик) наследуемый от Object.

Следовательно когда мы отправляем туда функцию (например _f1 из вашего примера), то данный pop становиться таким:

Navigator.of(context).pop<void>(_f1()) // более подробно: void pop<void>([void result])

И последний вопрос: почему анонимная функция не обновляет состояние виджета? Потому что у StatefulWidget обновлять состояние виджета может только setState.

Но не следует путать состояние виджета и состояние переменой, переменная будет обновлять свое состояние всегда, в то время как виджету нужно дать команду (setState) для перерисовки с новыми данными => обновить состояние виджета.


Почему тут ошибка:

Navigator.of(context).pop( _b = true; _visible = true; _text = 'Hide'; );

Вы спутали параметр с блоком кода.


Правильный вариант: который работает как вам нужно.

Answered by MiT on December 28, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP