코딩하는 제리

[Flutter/Project](Instagram Clone) Stream 데이터 구독 끊기 본문

Flutter/Project_InstaClone(완)

[Flutter/Project](Instagram Clone) Stream 데이터 구독 끊기

JerryCho 2021. 2. 17. 14:04

구독 정보를 저장하고 있다가 사용자가 로그아웃하면
더 이상 데이터를 전달 받지 않도록 구독을 취소함.

user_model_state.dart


소스코드 및 pubspec.yaml

// models/user_model_state.dart

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter_project_IJ/models/firestore/user_model.dart';

// 유저마다 다른 데이터를 위젯에 새로 출력하기 위해 작성.
class UserModelState extends ChangeNotifier {
  UserModel _userModel;

  // 구독 정보를 저장하고 있다가 사용자가 로그아웃하면
  // 더 이상 데이터를 전달 받지 않도록 구독을 취소함.
  StreamSubscription<UserModel> _currentStreamSub;

  UserModel get userModel => _userModel;

  // userModel 데이터가 바뀔 때 해당 위젯에 알려줌.
  set userModel(UserModel userModel) {
    _userModel = userModel;
    notifyListeners();
  }

  // currentStreamSub을 받아와서 _currentStreamSub에 저장.
  set currentStreamSub(StreamSubscription<UserModel> currentStreamSub) =>
      _currentStreamSub = currentStreamSub;

  clear() {
    // null이 아니면 실행.
    if(_currentStreamSub != null)
      _currentStreamSub.cancel();
    _currentStreamSub = null;
    _userModel = null;
  }
}
// main.dart

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_project_IJ/models/firebase_auth_state.dart';
import 'package:flutter_project_IJ/models/user_model_state.dart';
import 'package:flutter_project_IJ/repo/user_network_repository.dart';
import 'package:flutter_project_IJ/screens/auth_screen.dart';
import 'package:flutter_project_IJ/widgets/my_gallery.dart';
import 'package:flutter_project_IJ/widgets/my_progress_indicator.dart';
import 'package:provider/provider.dart';
import 'home_page.dart';
import 'constants/colors.dart';

void main() async {
  // 파이어베이스 사용을 위한 호출
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  FirebaseAuthState _firebaseAuthState = FirebaseAuthState();
  Widget _currentWidget;

  @override
  Widget build(BuildContext context) {
    _firebaseAuthState.watchAuthChange();
    return MultiProvider(
      providers: [
        // vallue() -> 기존에 생성되어 있는 인스턴스를 사용.
        ChangeNotifierProvider<FirebaseAuthState>.value(
          value: _firebaseAuthState,
        ),
        // (create:) -> 인스턴스 생성과 동시에 사용.
        ChangeNotifierProvider<UserModelState>(
          create: (_) => UserModelState(),
        )
      ],
      child: MaterialApp(
        home: Consumer<FirebaseAuthState>(
          builder: (BuildContext context, FirebaseAuthState firebaseAuthState,
              Widget child) {
            switch (firebaseAuthState.firebaseAuthStatus) {
              case FirebaseAuthStatus.signout:
                _clearUserModel(context);
                _currentWidget = AuthScreen();
                break;
              case FirebaseAuthStatus.singin:
                _initUserModel(firebaseAuthState, context);
                _currentWidget = HomePage();
                break;
              default:
                _currentWidget = MyProgressIndicator();
            }
            return AnimatedSwitcher(
              duration: Duration(milliseconds: 300),
              child: _currentWidget,
            );
          },
          child: HomePage(),
        ),
        theme: ThemeData(primarySwatch: white),
      ),
    );
  }

  void _initUserModel(
      FirebaseAuthState firebaseAuthState, BuildContext context) {
    UserModelState userModelState =
        Provider.of<UserModelState>(context, listen: false);
    // notifyListeners()로 받아온 데이터라면, listen: false를 입력.

    // 로그인이 되었을 때 UserModel 업데이트
    // 유저의 uid를 가져오려면 firebase_auth_state.dart 파일에서 User를 가져와야함.
    userModelState.currentStreamSub = userNetworkRepository
        .getUserModelStreams(firebaseAuthState.firebaseUser.uid)
        .listen((userModel) {
      userModelState.userModel = userModel;
    });
  }

  // 로그아웃 시 실행.
  void _clearUserModel(BuildContext context) {
    UserModelState userModelState =
        Provider.of<UserModelState>(context, listen: false);
    userModelState.clear();
  }
}
Comments