未来期间导航过渡会挂起

时间:2018-11-02 14:31:11

标签: flutter

我有以下代码,当在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 :(得分:1)

问题是sleep()方法冻结了ui。

您可以通过以下方式尝试使用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;
    });
  }
}

答案 1 :(得分:0)

Flutter recommends using the FutureBuilder widget when working with async data sources。例如:

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数据时保持运行。