【问题标题】:Flutter Riverpod redirection after entity creation实体创建后 Flutter Riverpod 重定向
【发布时间】:2022-09-27 16:22:52
【问题描述】:

我正在开发我的 Flutter 应用程序,并在创建实体(用户)后尝试设置重定向过程。状态管理由 Riverpod 处理。我将 Firebase 用于身份验证,将 Postgres 用于数据库。

存储库中的 insert 方法返回一个用户。使用StateNotifier 我只想检查该方法是否返回用户。如果返回用户,我设置一个成功状态对象 (CreateAccountStateSuccess),如果不是,我设置一个带有消息的错误状态对象。问题:我的saveUser 方法总是在我的StateNotifier 中返回null,即使我的用户保存在Firebase 和我的数据库中。我认为这是 Riverpod 的问题。任何想法?

我的存储库:

  Future<AppUser?> saveUser(String email, String nickname, String role,
      String firstname, String lastname) async {
    try {
      connection.open().then((value) async {
        Future<List<Map<String, Map<String, dynamic>>>> result = connection.mappedResultsQuery(
          \'insert into public.user(email,nickname,role,firstname,lastname) \'
          \'values(@emailValue,@nicknameValue,@roleValue,@firstnameValue,@lastnameValue) \'
          \'returning *\',
          substitutionValues: {
            \'emailValue\': email,
            \'nicknameValue\': nickname,
            \'roleValue\': role,
            \'firstnameValue\': firstname,
            \'lastnameValue\': lastname,
          },
          allowReuse: true,
          timeoutInSeconds: 30,
        );
        result.then((value) {
          final userFromDataBase = value[0][\'user\']!;
          return AppUser(
              email: userFromDataBase[\'email\'],
              nickname: userFromDataBase[\'nickname\'],
              role: userFromDataBase[\'role\'],
              firstname: userFromDataBase[\'firstname\'],
              lastname: userFromDataBase[\'lastname\']
          );
        });
      });
    } catch (e) {
      print(ErrorHandler(message: e.toString()));
      return null;
    }
    return null;
  }

我的 Firebase 方法为 Firebase 创建用户并使用我的存储库方法:

  Future<AppUser?> registerWithEmailAndPassword(String email, String password, String nickname, String role, String firstname, String lastname) async {
    FirebaseApp app = await Firebase.initializeApp(
        name: \'Secondary\', options: Firebase.app().options);
    try {
      UserCredential result =
      await FirebaseAuth.instanceFor(app: app).createUserWithEmailAndPassword(email: email, password: password);
      User? user = result.user;
      if (user == null) {
        throw Exception(\"No user found\");
      } else {
        try {
          return await UserRepository(user.email!).saveUser(email, nickname, role, firstname, lastname);
        } on PostgreSQLException catch (e) {
          print(\'CATCH POSTGRES EXCEPTION\');
          print(ErrorHandler(message: e.code.toString()));
        }
      }
    } on FirebaseException catch (e) {
      print(\'CATCH FIREBASE EXCEPTION\');
      print(ErrorHandler(message: e.code.toString()));
    }
    return null;
  }

我的控制器:

class CreateAccountController extends StateNotifier<CreateAccountState> {
  CreateAccountController(this.ref) : super(const CreateAccountStateInitial());

  final Ref ref;

  void register(String email, String password, String nickname, String role, String firstname, String lastname) async {
    state = const CreateAccountStateLoading();
    try {
      await ref.read(authRepositoryProvider).registerWithEmailAndPassword(
        email,
        password,
        nickname,
        role,
        firstname,
        lastname
      ).then((user){
        user != null ? state = const CreateAccountStateSuccess() : state = const CreateAccountStateError(\'Something went wrong with the user creation in database\');
      });
    } catch (e) {
      state = CreateAccountStateError(e.toString());
    }
  }
}

final createAccountControllerProvider =
StateNotifierProvider<CreateAccountController, CreateAccountState>((ref) {
  return CreateAccountController(ref);
});

我的状态对象:

class CreateAccountState extends Equatable {
  const CreateAccountState();

  @override
  List<Object> get props => [];
}

class CreateAccountStateInitial extends CreateAccountState {
  const CreateAccountStateInitial();

  @override
  List<Object> get props => [];
}

class CreateAccountStateLoading extends CreateAccountState {
  const CreateAccountStateLoading();

  @override
  List<Object> get props => [];
}

class CreateAccountStateSuccess extends CreateAccountState {
  const CreateAccountStateSuccess();

  @override
  List<Object> get props => [];
}

class CreateAccountStateError extends CreateAccountState {
  final String error;

  const CreateAccountStateError(this.error);

  @override
  List<Object> get props => [error];
}

我的屏幕:

class CreateAccountScreen extends StatefulHookConsumerWidget {
  const CreateAccountScreen({Key? key}) : super(key: key);

  @override
  ConsumerState<CreateAccountScreen> createState() => _CreateAccountScreenState();
}

class _CreateAccountScreenState extends ConsumerState<CreateAccountScreen> {
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  TextEditingController nicknameController = TextEditingController();
  TextEditingController roleController = TextEditingController();
  TextEditingController firstnameController = TextEditingController();
  TextEditingController lastnameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    ref.listen<CreateAccountState>(createAccountControllerProvider, ((previous, state) {
      if (state is CreateAccountStateError) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text(state.error.toString()),
          backgroundColor: Colors.red,
        ));
      }
      print(state.toString());
      if (state is CreateAccountStateSuccess) {
        context.goNamed(\'/\', params:
        {
          \'screenName\': \'users\'
        });
      }
    }));

    return Scaffold(
      appBar: AppBar(
          title: const Text(\'Create an account\'),
          elevation: 8.0,
          backgroundColor: Colors.deepOrangeAccent,
          actions: [
            TextButton.icon(
              icon: const Icon(
                Icons.logout_rounded,
                color: Colors.white,
              ),
              label: const Text(\'\', style: TextStyle(color: Colors.white)),
              onPressed: () async {
                ref.read(loginControllerProvider.notifier).signOut();
              },
            ),
          ]
      ),
      body: Padding(
          padding: const EdgeInsets.all(10),
          child: ListView(
            children: <Widget>[
              Container(
                  alignment: Alignment.center,
                  padding: const EdgeInsets.all(10),
                  child: const Text(
                    \'Ludocal 2\',
                    style: TextStyle(
                        color: Colors.deepOrange,
                        fontWeight: FontWeight.w500,
                        fontSize: 30),
                  )),
              Container(
                padding: const EdgeInsets.all(10),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? \"Enter an email\" : null,
                  controller: emailController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: \'Email Address\',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  obscureText: true,
                  validator: (value) =>
                  value == null || value.isEmpty ? \"Enter a password\" : null,
                  controller: passwordController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: \'Password\',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? \"Enter a nickname\" : null,
                  controller: nicknameController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: \'Nickname\',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? \"Enter a role\" : null,
                  controller: roleController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: \'Role\',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? \"Enter a firstname\" : null,
                  controller: firstnameController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: \'Firstname\',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? \"Enter a lastname\" : null,
                  controller: lastnameController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: \'Lastname\',
                  ),
                ),
              ),
              Container(
                  height: 50,
                  padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                  margin: const EdgeInsets.only(top:20),
                  child: ElevatedButton(
                    child: const Text(\'Create\', style: TextStyle(color: Colors.white)),
                    onPressed: () {
                      ref
                          .read(createAccountControllerProvider.notifier)
                          .register(emailController.text, passwordController.text, nicknameController.text,
                      roleController.text, firstnameController.text, lastnameController.text);
                    },
                  )),
            ],
          )),
    );
  }
}

    标签: postgresql flutter firebase dart riverpod


    【解决方案1】:

    问题出在saveUser 函数中。而不是使用.then 使用await。如下所示:

    Future<AppUser?> saveUser(String email, String nickname, String role,
        String firstname, String lastname) async {
      try {
        await connection.open();
        final result = await connection.mappedResultsQuery(
          'insert into public.user(email,nickname,role,firstname,lastname) '
          'values(@emailValue,@nicknameValue,@roleValue,@firstnameValue,@lastnameValue) '
          'returning *',
          substitutionValues: {
            'emailValue': email,
            'nicknameValue': nickname,
            'roleValue': role,
            'firstnameValue': firstname,
            'lastnameValue': lastname,
          },
          allowReuse: true,
          timeoutInSeconds: 30,
        );
    
        final userFromDataBase = result[0]['user']!;
        return AppUser(
          email: userFromDataBase['email'],
          nickname: userFromDataBase['nickname'],
          role: userFromDataBase['role'],
          firstname: userFromDataBase['firstname'],
          lastname: userFromDataBase['lastname'],
        );
      } catch (e) {
        print(ErrorHandler(message: e.toString()));
        return null;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-28
      • 2020-11-11
      • 2021-12-01
      • 1970-01-01
      • 2022-08-08
      • 1970-01-01
      • 2012-10-07
      • 2020-05-25
      相关资源
      最近更新 更多