Запрос Firebase Firestore с getX и авторизацией Firebase

#flutter #get #flutter-getx

Вопрос:

У меня есть небольшое приложение flutter, которое использует аутентификацию Firebase для входа в систему, а затем использует bindStream для запроса списка документов из Firestore. Это работает с самого начала/горячего перезапуска, но как только я выхожу из системы, я получаю ошибку разрешения firebase/firestore, и последующие входы в систему не обновляют поток. Я думал, что a GetxController удаляет потоки, созданные через bindStream , когда удаляется представление, использующее контроллер. В этом случае, когда я выхожу из системы , я отключаю все маршруты через Get.offAll , но, похоже, поток все еще активен, и именно тогда происходит ошибка разрешений. Но на самом деле я не совсем понимаю, что происходит.

главная.дротик

 void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Firebase.initializeApp();

  Get.put(LoginController());
  Get.put(AuthController(), permanent: true);

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'GetX Firebase Firestore',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SplashScreen(),
    );
  }
}
 

auth_controller.dart

 class AuthController extends GetxController {
  final AuthService _authService = AuthService();
  AuthService get authService => _authService;

  final LoginController _loginController = Get.find<LoginController>();
  LoginController get loginController => _loginController;

  Rxn<User> _user = Rxn<User>();
  User? get user => _user.value;

  @override
  void onReady() async {
    // bind auth state to _firebaesUser, but also give an initial value
    _user = Rxn<User>(_authService.currentUser);
    _user.bindStream(_authService.authState);

    //run every time auth state changes
    ever<User?>(_user, handleAuthChanged);

    super.onReady();
  }

  handleAuthChanged(User? user) {
    print("handleAuthChanged - ${user?.uid}");
    if (user == null) {
      Get.offAll(() => LoginScreen());
    } else {
      Get.offAll(() => HomeScreen(), binding: HomeBinding());
    }
  }
}
 

user_controller.dart

 class UserController extends GetxController {
  final UserRepository _userRepository = UserRepository();

  final repository = UserRepository();
  final users = Rx<List<FirestoreUser>>([]);

  late Rx<FirestoreUser> _firestoreUser;
  FirestoreUser get firestoreUser => _firestoreUser.value;

  @override
  void onInit() {
    super.onInit();
    final user = FirebaseAuth.instance.currentUser;

    if (user == null) return;

    _firestoreUser = Rx<FirestoreUser>(FirestoreUser.fromAuth(user));
    // get user data from firestore

    _firestoreUser.bindStream(_userRepository.getUserById(user.uid));

    // query user collection
    getAllUsers();
  }

  void getAllUsers() {
    users.bindStream(repository.getAllUsers());
  }
}
 

home_screen.dart

 class HomeScreen extends GetView<UserController> {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("All Sample Users"),
        actions: [
          IconButton(
            onPressed: () => Get.to(ProfileScreen()),
            icon: Icon(Icons.person),
          ),
        ],
      ),
      body: Obx(
        () => ListView.builder(
          itemCount: controller.users.value.length,
          itemBuilder: (context, index) {
            final user = controller.users.value[index];
            return ListTile(
              leading: CircleAvatar(
                backgroundImage: NetworkImage(user.photoURL),
              ),
              title: Text(user.displayName),
            );
          },
        ),
      ),
    );
  }
}
 

привязка к дому.дротик

 class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<UserController>(() => UserController(), fenix: true);
  }
}