You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建通用Dart库,实现可复用的Flutter身份认证功能

解决方案

这个需求完全可以实现,不需要传递类,通过函数回调/构造器参数的方式即可解耦公共库和上层业务页的依赖,以下是两种常用实现方案:

方案1:登录成功后将控制权交还给上层调用方(耦合度最低,推荐)

思路:LoginPage只处理登录逻辑,不负责跳转,登录成功后通过回调通知上层,上层自行处理状态更新和页面跳转逻辑。

第一步 修改公共库LoginPage定义

class LoginPage extends StatefulWidget {
  // 登录成功回调
  final VoidCallback onLoginSuccess;
  // 可选:登录失败回调
  final Function(String errorMsg)? onLoginFailed;

  const LoginPage({
    super.key,
    required this.onLoginSuccess,
    this.onLoginFailed,
  });

  @override
  _LoginPageState createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final _auth = FirebaseAuth.instance;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("身份认证"),
      ),
      body: SafeArea(
        // ... 原有登录表单逻辑
        child: () {
          if (userCredential != null) {
            setState(() {
              _isLoading = false;
            });
            // 触发成功回调,关闭当前登录页
            widget.onLoginSuccess();
            Navigator.pop(context);
          } else {
            // 触发失败回调
            widget.onLoginFailed?.call("登录失败,请检查账号密码");
          }
        }(),
      ),
    );
  }
}

第二步 上层应用调用修改

以app1.dart为例,app2.dart修改逻辑完全一致:

import 'package:myLibrary/login_page.dart';

class App1 extends StatefulWidget {
  @override
  _App1State createState() => _App1State();
}

class _App1State extends State<App1> {
  bool authenticated = false;

  @override
  Widget build(BuildContext context) {
    if (authenticated) {
      return Scaffold(...); // 应用主页逻辑
    } else {
      return Scaffold(
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => LoginPage(
                    // 登录成功后更新本地认证状态
                    onLoginSuccess: () {
                      setState(() {
                        authenticated = true;
                      });
                      // 可选:此处可添加本地存储认证状态、初始化用户信息等业务逻辑
                    },
                    onLoginFailed: (errorMsg) {
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(content: Text(errorMsg)),
                      );
                    },
                  ),
                ),
              );
            },
            child: const Text("去登录"),
          ),
        ),
      );
    }
  }
}

方案2:给LoginPage传递目标页构造器

如果希望跳转逻辑封装在LoginPage内部,可以给LoginPage传一个WidgetBuilder类型的参数,指定登录成功后跳转的页面:

公共库LoginPage修改

class LoginPage extends StatefulWidget {
  final WidgetBuilder successPageBuilder;

  const LoginPage({
    super.key,
    required this.successPageBuilder,
  });

  @override
  _LoginPageState createState() => _LoginPageState();
}

// 登录成功逻辑处修改为:
if (userCredential != null) {
  setState(() {
    _isLoading = false;
  });
  Navigator.pushReplacement(
    context,
    MaterialPageRoute(
      builder: widget.successPageBuilder,
    ),
  );
}

上层调用示例

// app1中调用
LoginPage(
  successPageBuilder: (context) => const App1HomePage(),
)

// app2中调用
LoginPage(
  successPageBuilder: (context) => const App2HomePage(),
)

优化提示

你原有代码中在build方法里直接执行Navigator.push逻辑不符合Flutter开发规范,会导致页面重复跳转、构建异常,建议把跳转逻辑放到initState或者用户点击事件的回调中执行。

内容的提问来源于stack exchange,提问作者SpeedyVV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 13:57:03