메모리에 이미지들에 대한 정보(URL, Bitmap, File, etc..)를 가지고 있다가 ImageView의 좌측 영역을 터치하면 이전 이미지를, 우측 영역을 터치하면 다음 이미지를 보여 주는 이른바 이미지 뷰어 기능을 구현하고 있었다. 구현 자체는 매우 간단했지만 현재 이미지에서 다른 이미지를 불러올 때 로딩하는 시간 때문인지 약 0.5초 정도 빈 화면이 표시된 뒤 이미지를 제대로 불러왔다. 걸리는 시간도 문제였지만 화면이 단색이었기 때문에 전환하는 과정에서 화면이 깜빡거리는 느낌을 줘서 보기 불편했다는 점이다.
서버에서 받아오는 이미지의 용량이 문제인가 싶어서 100kb 이하 크기의 이미지를 여러 개 준비하여 로드해보기도 하고 차이를 보기 위해서 5mb부터 최대 20mb 크기의 이미지를 로드해보기도 했는데 용량에 따른 로딩 속도 차이는 조금 있었지만 화면의 깜빡임은 그대로였다. 이미지를 URL로 바로 로드하는 기존 방식에서 Bitmap 객체에 로드하고 그대로 불러오는 방법, 캐시 메모리에 다운로드 했다가 로드하는 방법 등을 모두 시도해봤지만 깜빡거리는 현상은 해결되지 않았다.
이제껏 사용한 어플들에는 이미지 용량이 커서 로딩이 느린 적은 있어도 이렇게 깜빡거리는 현상은 본 적이 없었기에 굉장한 이질감과 불편함을 느꼈다. 용량에 따른 딜레이는 존재하더라도 최소한 이미지 전환에 있어서는 스무스하게 바뀌어야 사용자 입장에서 불편하다고 느끼지 않을 것이라 생각했기 때문에 방법을 찾다가 CustomTarget 클래스를 사용하는 방법을 찾았다. CustomTarget를 사용하는 방식은 into에 이미지를 표시할 객체에 대한 참조를 주는 게 아닌 CustomTarget 클래스를 구현하여 이미지를 로딩한다. 예전에 SimpleTarget 클래스(지금은 사용이 중지된 듯)를 사용해서 구현한 적이 있었지만 바로 view에 대한 참조를 넣는 것과 타겟 클래스를 사용하는 것의 차이를 몰랐기 때문에 잊어버리고 있었던 것 같다.
깜빡거리는 현상이 발생하는 코드(간략화한 예시)
Glide.with(this)
.load(url)
.into(binding.imageView);
CustomTarget 적용
URL 로딩
Glide.with(this)
.asBitmap()
.load(your_url)
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
binding.imageView.setImageBitmap(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
//
}
});
내부 저장소, 혹은 캐시 저장소에 있는 파일 로딩
Glide.with(this)
.asFile()
.load(file.getPath())
.into(new CustomTarget<File>() {
@Override
public void onResourceReady(@NonNull File resource, @Nullable Transition<? super File> transition) {
Bitmap bitmap = BitmapFactory.decodeFile(resource.getPath());
binding.imageView.setImageBitmap(bitmap);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
용량 문제
서버에서 받아오는 이미지의 용량이 문제인가 싶어서 100kb 이하 크기의 이미지를 여러 개 준비하여 로드해보기도 하고 차이를 보기 위해서 5mb 크기의 이미지를 로드해보기도 했다. 먼저 20mb 크기의 고용량 이미지를 구해서 로드했더니 약 1초 정도의 로딩 시간이 발생하고 10mb는 0.5초 정도, 5mb는 딜레이가 거의 없었다. CoustomTarget을 사용하지 않고 다이렉트로 view의 참조를 줬을 때랑 로딩 속도는 차이가 없었지만 깜빡임이 사라진 것을 확인할 수 있었다. 이미지 용량이 커서 늦게 로딩될 때는 기존 이미지를 표시하고 있는 상태에서 비동기로 로드가 완료되면 이미지가 전환되었다. 이미지가 아예 사라졌다가 다음 이미지를 불러오는 이전과는 확연히 달랐다.
Gif 로딩에 관한 기록
Glide.with(this)
.asGif()
.load(url)
.into(new CustomTarget<GifDrawable>() {
@Override
public void onResourceReady(@NonNull GifDrawable resource, @Nullable Transition<? super GifDrawable> transition) {
binding.imageView.setImageDrawable(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
서버에서 이미지를 로드할 때 여러 포맷을 테스트하였는데 JPG, JPEG, BMP, PNG 등은 문제없이 로드 되었지만 GIF만큼은 제대로 로드되지 않았다. 정확히는 into에 다이렉트로 view의 참조를 줄 경우 Gif의 특성인 애니메이션이 원활하게 동작했지만 이미지를 전환할 때 깜빡거리는 현상은 여전했고 이를 해결하기 위해서 CustomTarget을 사용하면 애니메이션이 동작하지 않았다. 테스트에 사용한 Gif 이미지들의 용량은 500kb~3mb이며 코드는 위와 같다.
이미지 전환에 있어서 매끄럽고 빠르게 Gif를 로딩하려면 ImageView+Glide의 조합으로는 무리라는 생각이 들었다. 다른 이미지 형식의 경우 왠만큼 용량이 높아도 메모리 상에(Bitmap 객체) 저장하고 불러오거나 캐시 디렉터리에 저장한 후 불러오면 스무스하게 로드되었다. 하지만 Gif는 Bitmap으로 저장하면 애니메이션이 제대로 동작하지 않고 이를 저장하기 위한 클래스 역시 GifDrawable 정도 뿐이었다. GifDrawable 타입의 리스트를 생성, 서버에서 읽은 gif 파일을 저장한 뒤 불러오기하면 Bitmap 객체 때와 마찬가지로 애니메이션이 동작하지 않았고 파일로 저장하고 이미지 전환을 시도하면 깜빡임을 없앨 수 없었다.
2개 이상의 Gif를 화면에 표시하려면 깜빡이는 문제를 감안하더라도 ImageView+Glide를 사용하거나 ViewPager2를 사용하는 것좋을 듯 하다. 나중에 ImageView+Glide로 스무스하고 빠른 Gif 이미지 전환 방법을 알게 되면 이 파트는 따로 빼내서 포스팅할 예정이다.
'안드로이드 > 안드로이드' 카테고리의 다른 글
[Android] arrays.xml 사용하기 (0) | 2023.09.25 |
---|---|
[Android] 안드로이드 스튜디오 Resource(*.xml) 관리 (0) | 2023.09.24 |
[Android/Java] Realm DB 라이브러리 추가 시 발생하는 repository 에러 (0) | 2021.09.25 |