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

kimmeanseo01님의 프로필 이미지

작성한 질문수

Flutter로 SNS 앱 만들기

게시글 정보 화면에 표시

CircleAvatar 성능 향상

해결된 질문

24.07.11 23:11 작성

·

92

0

안녕하세요 선생님 N번째 다시 복습하고 있는 수강생입니다.

저의경우, CircleAvator의 backgroundImage 속성에 ExtendedNetworkImageProvider 위젯을 사용하여 프로필 이미지를 받아와서 로딩하는데 시간이 대략 1.5초 쯤 소요되며, 그 1.5초의 시간 동안 기본 배경 색상인 보라색 원이 대신하여 나타납니다.

똑같이 ExtendedNetworkImageProvider 위젯을 사용하는 게시물의 이미지들은 프로필 사진보다 용량이 훨씬 큰데도 불구하고 거의 바로 이미지가 로딩되는데, 프로필 이미지의 로딩 속도가 더 느린 이유는 무엇일까요?

배경색상이 보이다가 네트워크 이미지가 로딩되는 방향 말고,

프로필 이미지의 로딩이 완전히 끝나기 전까지 fetching상태를 유지하여 로딩바를 보여주거나, 프로필이미지를 받아오는 속도를 높일 방법이 없을까요?

또는 이미지가 로딩되는 동안 배경색을 표시하는게 아니라, 로딩중을 표현할 수 있는 방법이 있을까요?

답변 기다리겠습니다. 감사합니다!

답변 2

0

kimmeanseo01님의 프로필 이미지
kimmeanseo01
질문자

2024. 07. 13. 13:48

코드 그대로 적용시켜보니 마음이 편안해집니다..

자세하고 꼼꼼한 답변 감사드립니다!

0

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

2024. 07. 12. 14:48

  1. 이미지를 표시할 때,
    게시물 이미지는 ExtendedImage.network 를 사용하고
    프로필 이미지는 ExtendedAssetImageProvider 를 사용하고 있습니다.

ExtendedImage 의 문서를 찾아보니 cache 사용 기본 설정이
ExtendedImage.network는 true, ExtendedAssetImageProvider 는 false 로 지정되어 있어서
로딩 속도에 차이가 발생한 것 같습니다.

아마도 이미지를 최초로 읽어올 때에는 게시물 이미지와 프로필 이미지 모두 로딩 시간에 큰 차이가 없고
이후에 화면 이동이나 새로 고침으로 동일한 이미지를 읽어올 경우에 cache 를 사용하지 않는
프로필 이미지의 로딩에 시간이 걸렸을 겁니다.

해결 방법은 ExtendedAssetImageProvider 의 cache 속성값을 true 로 지정하면 됩니다.

child: CircleAvatar(
  backgroundImage: userModel.profileImage == null
      ? ExtendedAssetImageProvider('assets/images/profile.png')
          as ImageProvider
      : ExtendedNetworkImageProvider(
          userModel.profileImage!,
          cache: true,
        ),
  radius: 18,
),

 

  1. 이미지를 로딩중일 때, 배경색이 아닌 로딩중임을 알려주는 위젯을 표시하는 방법은 ExtendedImage
    loadStateChanged 속성을 사용하면 됩니다.
    다만, 프로필 사진의 ExtendedAssetImageProvider 에서는 loadStateChanged 속성을 사용할 수 없기 때문에
    코드의 수정이 필요합니다.

     

    class AvatarWidget extends StatelessWidget {
      final UserModel userModel;
    
      const AvatarWidget({
        super.key,
        required this.userModel,
      });
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(
          onTap: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => ProfileScreen(
                  uid: userModel.uid,
                ),
              ),
            );
          },
          // ExtendedImage 를 사용하기 위해서 아래와 같이 수정
          child: userModel.profileImage == null
              ? ExtendedImage.asset(
                  // CircleAvatar 의 반지름(radius)이 18 이었으므로
                  // 이미지의 높이와 너비를 36으로 설정
                  width: 36,
                  height: 36,
                  // 이미지의 모양을 원형으로 설정
                  shape: BoxShape.circle,
                  'assets/images/profile.png',
                  // 이미지를 높이, 너비 36의 원형의 모양에 꽉 차도록 설정
                  fit: BoxFit.cover,
                )
              : ExtendedImage.network(
                  width: 36,
                  height: 36,
                  shape: BoxShape.circle,
                  userModel.profileImage!,
                  fit: BoxFit.cover,
                  // 이미지 로딩 상태에 따라 표시할 위젯을 설정
                  loadStateChanged: (state) {
                    switch (state.extendedImageLoadState) {
                      case LoadState.loading:
                      case LoadState.failed:
                        // 로딩중, 로딩 실패의 경우 CircularProgressIndicator 를 표시
                        return CircularProgressIndicator();
                      case LoadState.completed:
                        // 로딩 완료의 경우, 이미지를 그대로 표시하기 위해서 null 반환
                        // (ExtendedImage 의 문서에서 null 을 반환하도록 알려주고 있습니다.)
                        // https://pub.dev/packages/extended_image#demo-code
                        return null;
                    }
                  },
                ),
    
          // child: CircleAvatar(
          //   backgroundImage: userModel.profileImage == null
          //       ? ExtendedAssetImageProvider('assets/images/profile.png')
          //           as ImageProvider
          //       : ExtendedNetworkImageProvider(
          //           userModel.profileImage!,
          //           cache: true,
          //         ),
          //   radius: 18,
          // ),
        );
      }
    }