인프런 커뮤니티 질문&답변

강민성님의 프로필 이미지
강민성

작성한 질문수

Flutter로 메신저앱 만들기

채팅방 나가기 기능(2)

MessageCardWidget에 프로필 사진과 이름이 남는 이유

해결된 질문

작성

·

172

0

54강에서 채팅방 안에 카드 위젯에는 이름과 프로필사진이 남아있는 이유를 모르겠습니다. 앱을 껐다가 켜도 왜 초기화가 되지않는지 이유를 알고싶습니다.

답변 1

0

DEV MOO님의 프로필 이미지
DEV MOO
지식공유자

기대했던 결과와 실제로 출력된 결과를 자세히 말씀해주시면 감사하겠습니다. 그리고 프로젝트 전체의 소스 코드를 gobackad001@gmail.com 으로 보내주세요.

강민성님의 프로필 이미지
강민성
질문자

final messageList = ref.watch(chatProvider).messageList; 

메시지 카드위젯은 위와 같이 메시지리스트 안에 있는 유저모델을 참조합니다.


그런데 그 유저모델은 getMessageList 함수에서 업데이트 됩니다. (state = state.copywith)


따라서 채팅방의 메시지 카드위젯에 프로필과 이미지가 남아있는 이유가 getMessageList 함수에서

final userModel = await firestore
    .collection('users')
    .doc(messageDoc.data()['userId']) //message doc에 있는 userId로
    .get() //해당문서의  사용자의 정보를 가져와서해당 사용자의 정보를 가져와서
    .then((value) =>

message doc에 userid가 그대로 남아있어서 그 userId를 기반으로 users 컬랙션에서 프로필과 이름을 그대로 가져옵니다.

 

결론.
ChatState에 있는 userModel은 메시지 문서에 있는 userId를 통해 Firestore의 users 컬렉션에서 가져온 사용자 정보를 기반으로 구성됩니다. 이로 인해, 메시지 카드 위젯에서 해당 사용자 정보(이름, 프로필 사진 등)를 표시할 수 있게 됩니다.

 

혹시 제가 이해한게 맞을까요?

DEV MOO님의 프로필 이미지
DEV MOO
지식공유자

네, 정확하게 이해하고 계십니다.

강민성님의 프로필 이미지
강민성
질문자

오류관련해서 메일로 전체 소스코드를 보냈습니다!

DEV MOO님의 프로필 이미지
DEV MOO
지식공유자

0.연락처에 아무도 ktalk 유저가 없으면 오류발생
1.나간 채팅방에서 메시지를 보내면 오류발생
2.답장을 연 채로 채팅방을 나가면 오류발생
3.사진,동영상 보내는 창 바깥쪽 클릭 시 안빠져나와짐 (showmodalBottomsheet으로 해결)
4.친구목록에서 들어간다음 메시지를 하나도 안쳐도 채팅목록이 생성됨
5.상대방이 채팅방을 나가도 메시지카드위젯은 그대로 이름과 프로필이 남아있음
6.가끔 채팅방을 나갔다가 들어오면 알수없음으로 잠시 표기되는 오류

위와 같이 질문을 주셨습니다.

먼저 3, 4, 5번은 의도된 동작입니다.
6번은 재현이 되지 않아서 일단 답변을 보류하겠습니다.

  1. 나간 채팅방에서 메시지를 보내면 오류발생
    chat_repository.dart 의 sendMessage 함수에서 채팅방을 나간 상대방의 uid 는 빈 문자열 입니다. firestore 컬렉션의 id 값이 빈 문자열인 문서를 지정해서 발생하는 문제이므로 아래와 같이 수정합니다(보내주신 소스 코드의 184행 입니다).

    for (final userModel in chatModel.userList) {
      if (userModel.uid.isNotEmpty) { // 추가
        transaction.set(
          firestore
              .collection('users')
              .doc(userModel.uid)
              .collection('chats')
              .doc(chatModel.id),
          chatModel.toMap(),
        );
      }
    }

    id 값이 빈 문자열이 아닌 경우에만 로직을 수행하도록 수정했습니다.

  2. 답장을 연 채로 채팅방을 나가면 오류발생
    message_input_field_widget.dart 에서 뒤로가기 버튼 터치시, 답글 위젯의 닫기 버튼을 터치했을 때와 동일한 로직을 수행하도록 로직을 추가합니다(보내주신 코드에서 248행 입니다).

    return PopScope(
      canPop: !isEmojiShow,
      onPopInvoked: (didPop) {
        setState(() {
          ref.read(replyMessageModelProvider.notifier).state = null; // 추가
          isEmojiShow = false;
        });
      },


    0.연락처에 아무도 ktalk 유저가 없으면 오류발생
    0번의 경우도 보내주신 코드로 테스트를 해봤지만 에러가 발생하지 않았습니다.
    (친구 목록에 아무도 표시되지 않는 상태에서 테마 변경, 언어 변경)

강민성님의 프로필 이미지
강민성
질문자

error: (error, stackTrace) {
  logger.e(error.toString());
  context.loaderOverlay.hide();
  GlobalNavigator.showAlertDialog(text: error.toString());
  return Center(child: Text('데이터를 불러올 수 없습니다.'));
}

friend_list_screen에서 친구가 한명도 없으면 error가 실행되는데

GlobalNavigator.showAlertDialog(text: error.toString());

이 부분이 충돌이 일어나는것 같습니다.

 

해결방법

WidgetsBinding.instance.addPostFrameCallback((_) {
  GlobalNavigator.showAlertDialog(text: error.toString());
});
  • WidgetsBinding.instance.addPostFrameCallback은 현재 프레임이 끝난 후에 코드를 실행하게 합니다. 이렇게 하면 Navigator 충돌을 피할 수 있습니다.

  • 이 방법을 사용하면 Future를 반환하지 않아도 됩니다.

이 방법을 사용하면 Navigator와 관련된 충돌을 피하면서 에러 다이얼로그를 안전하게 표시할 수 있습니다.

알려주신데로 나머지 코드는 잘 해결할 수 있었습니다. 감사합니다!!

강민성님의 프로필 이미지
강민성

작성한 질문수

질문하기