读取提供者的状态而不再次传递参数

问题描述 投票:0回答:1

首先我要说的是,我对 Flutter 非常陌生,并且来自 Rails,其中 current_user 的设置要简单得多。 我正在创建一个功能性的 currentUserProvider:

@riverpod
User currentUser(CurrentUserRef ref, User user) {
    User currentUser = user;
    return currentUser;
  }
}

这是建立在另一个提供商内的成功登录的基础上的,该提供商检查登录是否成功并保存其状态:

enum AuthenticationState {
  initial,
  loading,
  success,
  error,
}

@riverpod
class Authentication extends _$Authentication {
  @override
  AuthenticationState build() {
    return AuthenticationState.initial;
  }

  Future<void> login() async {
    //API Call made here and status returned:
    if (response.statusCode == 200) {
      User currentUser = User.fromJson((json.decode(response.body))['data']['attributes']);
      currentUser = currentUser.copyWith(jwt: token);
      ref.read(currentUserProvider(user: currentUser));
      state = AuthenticationState.success;
    } else {
      await SecureStorage().deleteSecureData('jwt');
      state = AuthenticationState.error;
    }
  }
}

我的问题是,在接下来的任何地方,我只想要 currentUserProvider 的缓存值,但它希望我将用户对象作为参数传递给它。 我不想将用户参数设置为可选,因为它永远不应该为空,并且用户会被重定向到登录屏幕。 有什么办法可以获取它的当前状态吗?我不想让参数成为可选的,因为 User 对象不能为空。

flutter riverpod
1个回答
0
投票

AsyncNotifier
的状态是
AsyncValue<User>
的一个实例,它具有例如方法:

  • isLoading
  • isRefreshing
  • isReloading
  • hasError

除了

authenticationProvider
currentUserProvider
,您还可以:

import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'user_notifier.g.dart';

class User {
  const User(this.id);
  const User.nobody() : id = -1; 
  final int id;
}

@riverpod
class UserNotifier extends _$UserNotifier {
  @override
  Future<User> build() async {  // Alternatively Future<User?>
    return const User.nobody(); //    and return null.
  }

  Future<void> login() async { // Later probably with credentials
    // Set the state to loading
    state = const AsyncValue.loading();
    // Set the state data
    state = await AsyncValue.guard(() async {
      return await Future.delayed(
        const Duration(seconds: 5),
        () => const User(1),
      );
    });
  }

  // This getter might not be required. The information is already
  // available. 
  AuthenticationState get authenticationState {
    if (state.isLoading) {
      return AuthenticationState.loading;
    }else if(state.hasError){
      return AuthenticationState.error;
    }
    ...
  }
}

在下面的示例中,页面最初显示“无人登录”。单击登录后,将显示加载指示器,最后显示用户 ID。

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../providers/user_notifier.dart';

class UserPage extends ConsumerWidget {
  const UserPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userAsyncValue = ref.watch(userNotifierProvider);

    return Scaffold(
      appBar: AppBar(
        title: const Text('User Page'),
      ),
      body: Center(
        child: switch (userAsyncValue) {
          AsyncData(value: const User.nobody()) => const Text('Nobody logged in'),
          AsyncData(value: final user) => Text(user.id.toString()),
          AsyncError(:final error) => Text('Error: $error'),
          _ => const Center(child: CircularProgressIndicator()),
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await ref.read(userNotifierProvider.notifier).login();
        },
        tooltip: 'Log in',
        child: const Icon(Icons.login),
      ), 
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.