簡體   English   中英

Flutter 創建實體后的 Riverpod 重定向

[英]Flutter Riverpod redirection after entity creation

我正在開發我的 Flutter 應用程序,我嘗試在創建實體(用戶)后設置重定向過程。 state 管理由 Riverpod 處理。 我將 Firebase 用於身份驗證,將 Postgres 用於數據庫。

存儲庫中的 insert 方法返回一個用戶。 使用StateNotifier我只想檢查該方法是否返回用戶。 If the user is returned I set a success state object (CreateAccountStateSuccess), if it's not I set an error state object with a message. 問題:我的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;
  }

我的 controller:

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);
});

我的 state 對象:

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);
                    },
                  )),
            ],
          )),
    );
  }
}

問題出在saveUser function 中。 而不是使用.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;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM