Android Fresco 이미지 로드 최적화 방안

최적화 배경
일반적인 상황 에서 Fresco 그림 로드 는 Simple DraweeView 를 사용 해 야 합 니 다.이 컨트롤 은 자신의 크기 에 따라 필요 한 그림 을 자동 으로 불 러 올 수 없습니다.즉,N 입 니 다.×N 의 UI 컨트롤,뒤에 불 러 온 실제 그림 은 2N 일 수 있 습 니 다.×2N。이 로 인해 실제 응용 운행 과정 에서 메모리 사용 효율 이 높 지 않 아 메모리 최적화 가 필요 하 다.

일부 입문 급 하드웨어 설비 에서 특히 뚜렷하게 나타난다.프로그램의 운행 시간 이 증가 함 에 따라 OOM 의 위험 도 끊임없이 커진다.
Fresco 버 전:1.13.0
데이터 레코드
설명 컨트롤 크기 480×270

<com.facebook.drawee.view.SimpleDraweeView
  android:id="@+id/simple_drawee_view"
  android:layout_width="480dp"
  android:layout_height="270dp"
  android:layout_alignParentBottom="true"
  android:layout_centerHorizontal="true"
  app:layout_constraintBottom_toBottomOf="parent"
  app:layout_constraintLeft_toLeftOf="parent"
  app:layout_constraintRight_toRightOf="parent"
  app:layout_constraintTop_toTopOf="parent" />
그림 코드 를 불 러 오고 Fresco 의 setImageURI 를 호출 합 니 다.

val mImageUrl = "https://static.runoob.com/images/demo/demo4.jpg"
val simple_drawee_view = findViewById<SimpleDraweeView>(R.id.simple_drawee_view)
simple_drawee_view.setImageURI(mImageUrl)
실행 후 dump 메모 리 는 다음 과 같 습 니 다.메모리 의 그림 크기 는 1920 입 니 다.×1080,즉 이때 Simple DraweeView 는 네트워크 의 원본 그림 크기 에 따라 불 러 옵 니 다.메모리 사용량 은 8294475 Bytes=7.91Mb 입 니 다.한 장의 그림 이 8Mb 에 가 까 운 것 을 차지 하고 그림 이 매우 풍부 한 페이지 장면 을 표시 하 는 과정 에서 그림 의 총 메모리 사용 크기 는 매우 아름 다 울 것 이다.만약 에 이 페이지 가 또 메모리 가 누설 된다 면 더욱 아름 다 울 것 이다.

480 만 불 러 오 면×270 크기 의 그림,메모리 사용량 은 518475 Bytes=0.49Mb 입 니 다.원래 1920 에 비하 면×1080 사이즈,메모리 94%감소!

최적화 방안
Fresco 는 resize api 를 제공 하여 호출 자가 그림 디 코딩 전에 메모리 에 있 는 그림 의 크기 를 수정 할 수 있 도록 합 니 다.api 는 대체적으로 다음 과 같 습 니 다.

ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
 .setResizeOptions(new ResizeOptions(width, height))
 .build();
PipelineDraweeController controller = Fresco.newDraweeControllerBuilder()
 .setOldController(mDraweeView.getController())
 .setImageRequest(request)
 .build();
mSimpleDraweeView.setController(controller);
이 방안 은 낮은 버 전에 서 기본적으로 jpg 그림 만 지원 합 니 다.다른 그림 형식 을 지원 하려 면 image pipeline 을 설정 할 때 isDownsample 설정 을 추가 해 야 합 니 다.또한 생 긴 그림 의 사 이 즈 는 대충 제어 할 수 있 을 뿐 그림 은 정확 한 사이즈 로 수정 할 수 없다.

.setDownsampleEnabled(true)
이 방안 은 현저 한 단점 이 있 습 니 다.그것 은 바로 페이지 의 적합성 이 매우 떨 어 지 는 것 입 니 다.View 층 의 생명 주기 에 맞 춰 컨트롤 의 너비 가 높 은 시 기 를 동태 적 으로 얻 을 수 있 도록 호출 해 야 합 니 다.성숙 한 프로젝트 프로젝트 프로젝트 에 대해 코드 변 동량 이 너무 많 고 최적화 원가 가 너무 높 습 니 다.Simple DraweeView 를 작성 하 는 하위 클래스 를 최적화 시 키 고 위로 전환 하 며 View 계층 코드 의 변경 을 최대한 줄 이 고 xml 레이아웃 파일 의 컨트롤 설명 만 수정 하면 됩 니 다.프로젝트 구성 도 는 다음 과 같다.

그 중에서 Desired Simple DraweeView 는 Simple DraweeView 의 하위 클래스 로 onWindow FocusChanged 방법 리 셋 에서 컨트롤 의 구체 적 인 너비 와 높이 를 명 확 히 알 수 있 고 그 다음 에 그림 로드 작업 을 할 수 있 습 니 다.

public class DesiredSimpleDraweeView extends SimpleDraweeView {

 Uri mUri;
 Object mCallerContext;

 public DesiredSimpleDraweeView(Context context) {
  super(context);
 }

 @Override
 public void setImageURI(Uri uri, Object callerContext) {
  mUri = uri;
  mCallerContext = callerContext;
 }

 private void setImageURI(int width, int height) {
  try {
   ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(mUri)
     .setResizeOptions(new ResizeOptions(width, height))
     .build();
   DraweeController controller =
     getControllerBuilder()
       .setOldController(getController())
       .setImageRequest(imageRequest)
       .build();
   setController(controller);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 @Override
 public void onWindowFocusChanged(boolean hasWindowFocus) {
  super.onWindowFocusChanged(hasWindowFocus);
  if (hasWindowFocus) {
   setImageURI(getWidth(), getHeight());
  }
 }
}
setImageURI(Uri,Object)방법 을 복사 하여 uri 와 caller Context 를 잠시 저장 하고 onWindow Focus Changed 를 리 셋 한 후 컨트롤 너비 에 따라 그림 을 불 러 옵 니 다.이렇게 하면 위로 전환 을 이용 하여 View 층 의 코드 는 변경 할 필요 가 없고 xml 파일 에서 컨트롤 성명 을 교체 하면 메모리 이 용 률 을 현저히 높 일 수 있 습 니 다.
주의 사항
성능 최 적 화 는 끝 이 없 는 길이 다.가장 강력 한 방안 은 없고 가장 적합 한 방안 만 있다.그림 로드 사 이 즈 를 정확하게 제어 하려 면 필요 에 따라 로드 하 는 것 이 좋 을 수도 있 습 니 다.
이상 은 안 드 로 이 드 프레스 코 이미지 로드 최적화 방안 의 상세 한 내용 입 니 다.안 드 로 이 드 프레스 코 이미지 로드 최적화 에 관 한 자 료 는 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기