навигационный переход зависает во время будущего - PullRequest
0 голосов
/ 02 ноября 2018

у меня есть код ниже, что когда кнопка нажата на Page1 (), будущее выполняется, когда Page2 () загружается, но CircularProgressIndicator () «зависает», пока будущее не завершится. Я попробовал это и с BottomNavigationBar, и «слайд» тоже завис на полпути.

Есть ли более идиоматический способ сделать это так, чтобы Page2 () полностью рендерился во время работы будущего?

//-----------------------
    //main.dart
    //-----------------------

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      routes: {
        '/' : (BuildContext context) => Page1(),
        '/page2' : (BuildContext context) => Page2()
      }
    );
  }
}

//-----------------------
//page1.dart
//-----------------------

class Page1 extends StatelessWidget {

  @override
    Widget build(BuildContext context) {
       return Scaffold(
         appBar: AppBar(title: Text('Page 1')),
         body: Container(
           child: Column(children: <Widget>[
             Text('Page 1 header'),
             RaisedButton(
               child: Text('Click me'),
               onPressed: ()  {
                 Navigator.of(context).pushReplacementNamed('/page2');
                 })
           ],),)
         );
    }
}

//-----------------------
//page2.dart
//-----------------------

class Page2 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _Page2State();
  }
}

class _Page2State extends State<Page2> {
  MainModel model = MainModel();

  void initState() {
    model.fetchData();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Page 2')),
        body: ScopedModel<MainModel>(
            model: model,
            child: ScopedModelDescendant(
                builder: (context, child, MainModel model) {
              if (model.isLoading) {
                return Center(child: CircularProgressIndicator());
              } else {
                return Container(
                    child: Column(
                  children: <Widget>[
                    Text('Page 2 body'),
                  ],
                ));
              }
            })));
  }
}


//-----------------------
//main_model.dart
//-----------------------
class MainModel extends Model {

    bool _isLoading = false;
    bool get isLoading => _isLoading;

  void fetchData() async {

      _isLoading = true;
      notifyListeners();

      final String url = 'https://jsonplaceholder.typicode.com/todos/1';

      await http.get(url)
          .then<Null>((http.Response response) {
            print('${DateTime.now()} In http response and about to sleep');
            sleep(const Duration(seconds:5));
            print('${DateTime.now()} done sleeping');

            _isLoading = false;
            notifyListeners();
            return;
          }
      ).catchError((error) {
        print('Error: $error');
        _isLoading = false;
        notifyListeners();
        return;
      });

  }

}

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Проблема в том, что метод sleep() замораживает пользовательский интерфейс.

Вы можете попробовать Future.delayed() следующим образом:

class MainModel extends Model {
  bool _isLoading = false;

  bool get isLoading => _isLoading;

  void fetchData() {
    _isLoading = true;
    notifyListeners();

    final String url = 'https://jsonplaceholder.typicode.com/todos/1';

    http.get(url).then<Null>((http.Response response) {
      print('${DateTime.now()} In http response and about to sleep');
      Future.delayed(Duration(seconds: 5), () {
        _isLoading = false;
        notifyListeners();
        print('${DateTime.now()} done sleeping');
      });
    }).catchError((error) {
      print('Error: $error');
      _isLoading = false;
      notifyListeners();
      return;
    });
  }
}
0 голосов
/ 02 ноября 2018

Flutter рекомендует использовать виджет FutureBuilder при работе с асинхронными источниками данных . Например:

FutureBuilder<Post>(
  future: fetchPost(),
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text(snapshot.data.title);
    } else if (snapshot.hasError) {
      return Text("${snapshot.error}");
    }

    // By default, show a loading spinner
    return CircularProgressIndicator();
  },
);

Таким образом, CircularProgressIndicator будет продолжать работать, пока ваша Page2 загружает данные API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...