【问题标题】:Flutter Getx How to navigate to other page in StreamBuilderFlutter Getx 如何在 StreamBuilder 中导航到其他页面
【发布时间】:2022-01-06 02:51:21
【问题描述】:

我正在使用 firebase_auth 进行注册和登录。 我遇到了 Streambuilder 的问题。

我想显示的页面取决于用户是否登录。似乎工作正常。 但是,问题是我不能使用 Get.off('/app');在 StreamBuilder 和 FutureBuilder 中。 如果我不能使用 Getx.off('/app');用户只需按下后退按钮即可返回,并且 我想避免这种情况,所以我尝试使用 Get.off 页面路由。

但是,正如 vs 代码所示,FutureBuilder 和 StreamBuilder 的构建器返回 Widget, 而且我不知道如何编码。

对这个问题有什么建议吗?

    // main.dart
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GetMaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Karrot Market Clone',
          theme: ThemeData(
            primaryColor: Colors.black,
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
            appBarTheme: AppBarTheme(
              color: Colors.white,
            ),
          ),
          initialBinding: InitBinding(),
          initialRoute: '/',
          getPages: [
            GetPage(
              name: '/',
              page: () => BridgeFirebase(),
            ),
            GetPage(
              name: '/bridge_page',
              page: () => BridgePage(),
            ),
            GetPage(
              name: '/app',
              page: () => App(),
              transition: Transition.rightToLeft,
            ),
            GetPage(
              name: '/start',
              page: () => Start(),
            ),
            GetPage(
              name: '/login',
              page: () => Login(),
              transition: Transition.rightToLeft,
            ),
            GetPage(
              name: '/signup',
              page: () => SignUp(),
              transition: Transition.rightToLeft,
            ),
          ],
        );
      }
    }
      class BridgeFirebase extends StatelessWidget {
      const BridgeFirebase({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: Firebase.initializeApp(),
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Center(child: Text('Firebase load fail'));
            }
            if (snapshot.connectionState == ConnectionState.done) {
              return BridgePage();
            }
            return Center(
              child: CircularProgressIndicator(
                color: ColorsKM.primary,
              ),
            );
          },
        );
      }
    }
    class BridgePage extends StatelessWidget {
      const BridgePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return StreamBuilder(
          stream: FirebaseAuth.instance.authStateChanges(),
          builder: (BuildContext context, AsyncSnapshot<User?> snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Splash();
            }
            if (snapshot.hasData) {
              return App();
            } else {
              return Start();
            }
          },
        );
      }
    }
// app.dart
class App extends GetView<AppController> {
  const App({Key? key}) : super(key: key);

  Widget _bodyWidget() {
    switch (RouteName.values[controller.currentIndex.value]) {
      case RouteName.HOME:
        return Home();
        break;
      case RouteName.MYLOCAL:
        return MyLocal();
        break;
      case RouteName.NEARBY:
        return Nearby();
        break;
      case RouteName.CHATS:
        return Chats();
        break;
      case RouteName.MYKARROT:
        return MyKarrot();
        break;
    }
    return Container();
  }

  BottomNavigationBarItem _bottomNavigationBarItem(
      String iconName, String label) {
    return BottomNavigationBarItem(
      icon: Padding(
        padding: EdgeInsets.only(bottom: 5.0),
        child: SvgPicture.asset('assets/svg/${iconName}_off.svg', width: 22),
      ),
      activeIcon: Padding(
        padding: EdgeInsets.only(bottom: 5.0),
        child: SvgPicture.asset('assets/svg/${iconName}_on.svg', width: 22),
      ),
      label: label,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Obx(
        () {
          return _bodyWidget();
        },
      ),
      bottomNavigationBar: Obx(
        () => BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          currentIndex: controller.currentIndex.value,
          selectedFontSize: 12.0,
          showSelectedLabels: true,
          selectedItemColor: Colors.black,
          selectedLabelStyle: TextStyle(color: Colors.black),
          onTap: controller.changePageIndex,
          items: [
            _bottomNavigationBarItem('home', 'home'),
            _bottomNavigationBarItem('notes', 'neighbor'),
            _bottomNavigationBarItem('location', 'nearby'),
            _bottomNavigationBarItem('chat', 'chat'),
            _bottomNavigationBarItem('user', 'my karrot'),
          ],
        ),
      ),
    );
  }
}
// app_controller.dart
enum RouteName {
  HOME,
  MYLOCAL,
  NEARBY,
  CHATS,
  MYKARROT,
}

class AppController extends GetxService {
  static AppController get to => Get.find();

  late RxInt currentIndex = 0.obs;

  void changePageIndex(int index) {
    currentIndex(index);
  }
}

【问题讨论】:

    标签: flutter navigation flutter-getx


    【解决方案1】:

    因为当您在 Streambuilder 中导航时构建方法未完成,所以您可以延迟一些时间到构建方法完成然后导航。当您想在 Streambuilder 中导航时执行此操作:

    Future.delayed(Duration.zero).then((value) => Get.off('/app'));
    

    或者只是在您的控制器或 bloc 类中导航。

    【讨论】:

    • 感谢您的回答,但我无法理解您的意思。你的意思是我应该返回'return Future.delayed(Duration.zero).then((value) => Get.off('/app'));'而不是返回 App()?我试过了,我得到一个错误'返回类型'Future?>'不是'Widget',正如闭包的上下文所要求的那样。'。您能否详细说明您的答案?请原谅我缺乏知识?
    • 不,你想在构建方法中使用导航的任何地方,在 Future.delayed 中使用它,你不应该在构建方法中返回它
    • 在我的代码中,我使用了 StreamBuilder 并且每个 if 语句都有 return Widget。我认为我应该使用 StreamBuilder 来路由页面取决于快照是否有数据。你的意思是我可以用另一种方法来实现我想做的事情,就像直接返回 Widget 一样?你能给我更多的细节或代码示例吗?
    • 你在哪里导航?给我一些代码
    • 我添加了 app.dart 和 app_controller.dart 代码。我想在用户登录时使用 Get.off 导航到 App 类视图。
    猜你喜欢
    • 2020-07-29
    • 1970-01-01
    • 2021-09-13
    • 2020-07-31
    • 2021-07-18
    • 2023-01-13
    • 1970-01-01
    • 2022-11-08
    • 2018-09-27
    相关资源
    最近更新 更多