如何从没有上下文的类中使用Navigator?

时间:2019-09-18 15:17:45

标签: flutter

我写了一个小应用程序,可以在启动屏幕上打印2342HomePage,然后等待2秒钟并完全切换到context。我无法弄清楚如何在Widget之外使用Navigator的问题,因为它需要import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; Stream<int> stream; StreamController<int> myStreamController = StreamController(); void main() { MyClass myClass = MyClass(); WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]) .then((_) { runApp(new MyApp()); }); } class MyClass { MyClass() { stream = Stream<int>.periodic(Duration(seconds: 1), (t) => t + 1).take(3); myStreamController.addStream(stream).then( (done) { Future.delayed(Duration(seconds: 2), () { // wait 2 seconds before Showing HomePage myStreamController.addStream( Stream.value(42) ); // Navigator.push(context, route) // But we do not have context in this class!! }); } ); // stream.pipe(myStreamController.sink); } } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp(title: "Hello", routes: { '/': (context) => SplashScreen(), '/home': (context) => HomePage(), }); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Container( child: Text("Hello World, Home Page"), ), ); } } class SplashScreen extends StatefulWidget { @override SplashScreenState createState() => SplashScreenState(); } class SplashScreenState extends State<SplashScreen> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: Container( child: DefaultTextStyle( style: TextStyle( fontSize: 24, color: Colors.black54 ), child: StreamBuilder( stream: myStreamController.stream, builder: (context, snapshot) { if (snapshot.hasData) { switch (snapshot.data) { case 1: return Text("${snapshot.data}"); case 2: return Text("${snapshot.data}"); case 3: return Text("${snapshot.data}"); default: return Text("${snapshot.data}"); } } else return CircularProgressIndicator(); }) ) ), )); // return } } class DigitProgressIndicator extends StatelessWidget { String text; DigitProgressIndicator(this.text); @override Widget build(BuildContext context) { return Text(text); } }

这是我的代码:

{{1}}

2 个答案:

答案 0 :(得分:0)

只需将其移动到显示42的位置即可

class SplashScreenState extends State<SplashScreen> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Container(
              child: DefaultTextStyle(
                  style: TextStyle(
                      fontSize: 24,
                      color: Colors.black54
                  ),
                  child: StreamBuilder(
                      stream: myStreamController.stream,
                      builder: (context, snapshot) {
                        if (snapshot.hasData) {
                          switch (snapshot.data) {
                            case 1:
                              return Text("${snapshot.data}");
                            case 2:
                              return Text("${snapshot.data}");
                            case 3:
                              return Text("${snapshot.data}");
                            default:
                              Navigator.push(context, route);  // But now we have context in this class!!
                              return Text("${snapshot.data}");

                          }
                        } else
                          return CircularProgressIndicator();
                      })
              )
          ),
        ));

    // return
  }
}

您还可以将NavigatorFuture.delayed包裹起来,这样一来,它就会显示42。

也是一个提示:

Navigator是一个小部件,不是管理类,Navigator.of(context)将为您提供最接近的祖先Navigator小部件。在pushing小部件上Navigator的脚手架意味着您要在具有Stack个孩子的Scaffold小部件之上添加小部件。

答案 1 :(得分:0)

我发现了两种从业务逻辑切换屏幕的方法。第一个(我认为最好)。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

Stream<int> stream;

StreamController<int> myStreamController = StreamController.broadcast();

void main() {
  MyClass myClass = MyClass();

  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft])
      .then((_) {
    runApp(new MyApp());
  });
}


class MyClass {
  MyClass() {
    stream = Stream<int>.periodic(Duration(seconds: 1), (t) => t + 1).take(3);
    myStreamController.addStream(stream).then(
      (done) {
      Future.delayed(Duration(seconds: 2), () { // wait 2 seconds before Showing HomePage
            myStreamController.addStream( Stream.value(42) ); 

          });
      }
    );


  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: "Hello", 
    routes: 
      {
        '/': (context) => SplashScreen(),
        '/home': (context) => HomePage(),
      },

    );

  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context)
  {
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Text("Hello World, Home Page"),
      ),
    );
  }
}

class SplashScreen extends StatefulWidget {
  @override
  SplashScreenState createState() => SplashScreenState();
}

class SplashScreenState extends State<SplashScreen> {

  @override
  void initState() {
    myStreamController.stream.listen((data) {
      if (data == 42)
      {
        Navigator.pushNamed(context, '/home');
      }
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Container(
            child: DefaultTextStyle(
              style: TextStyle(
                fontSize: 24,
                color: Colors.black54
              ),
              child: StreamBuilder(
                  stream: myStreamController.stream,
                  builder: (context, snapshot) {
                    if (snapshot.hasData) {
                      switch (snapshot.data) {
                        case 1:
                          return Text("${snapshot.data}");
                        case 2:
                          return Text("${snapshot.data}");
                        case 3:
                          return Text("${snapshot.data}");
                        default:
                          return Text("${snapshot.data}");                          
                      }
                    } else
                      return CircularProgressIndicator();
                  })
            )
                  ),
        ));

  }
}

此处介绍第二种方法http://stacksecrets.com/flutter/navigation-when-there-is-no-context