Android 개발 중 Bitmap 고 효율 로 딩 사용 에 대한 상세 설명

5553 단어 AndroidBitmap
Android 가 단일 응용 프로그램 에 가 하 는 메모리 제한,예 를 들 어 16MB 로 인해 Bitmap 를 불 러 올 때 메모리 가 넘 치기 쉽 습 니 다.본 고 는 주로 Bitmap 메모리 와 Bitmap 의 효율 적 인 로드 를 분석 하 는 두 가지 내용 을 포함 합 니 다.
메모리 사용량
bitmap 의 메모리 가 져 오기,android 가 제공 하 는 방법 bitmap.getByteCount()
현재 mipmap-xhdpi 디 렉 터 리 에 200*200 픽 셀 의 그림 이 있 으 면 불 러 오기 를 실행 하고 출력 사 이 즈 를 봅 니 다.
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.mipmap.btn_go);
bitmap.getByteCount()의 출력 결 과 는 360000 입 니 다.
현재 그림 을 mipmap-xxhdpi 로 옮 깁 니 다.
bitmap.getByteCount 의 출력 결 과 는 160000 입 니 다.
그럼 mipmap-xhdpi 디 렉 터 리 아래 왜 이렇게 커 요?
density 비트 맵 메모리 영향
서로 다른 mipmap 디 렉 터 리 에 대응 하 는 서로 다른 density 장치 입 니 다.density 는 장치 의 고유 매개 변수 입 니 다.density Dpi 와 함께 장치 와 관련 된 것 입 니 다.화면 이 인치 당 몇 개의 점(픽 셀 이 아 닌 점)에 대응 하 는 지 표시 합 니 다.

위 는 공식 적 으로 제공 하 는 비교적 전형 적 인 그림 입 니 다.서로 다른 디 렉 터 리 는 서로 다른 density 를 대표 합 니 다.예 를 들 어 xhdpi 가 대표 하 는 density 는 2 입 니 다.여기 서 density Dip 에 대한 density 기준 은 160 입 니 다.즉,mdpi 에 대응 하 는 density Dpi 는 160 이 고 xhdpi 에 대응 하 는 density Dpi 는 320 입 니 다.마찬가지 로 xx hdpi 에 대응 하 는 density Dpi 는 480 입 니 다.
density 와 density Dpi 는 Android 에서 표준 API 를 받 을 수 있 습 니 다.다음 과 같 습 니 다.

DisplayMetrics displayMetrics=new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
Log.i(TAG, displayMetrics.densityDpi+"");
Log.i(TAG,displayMetrics.density+"");
제 핸드폰 의 출력 결과 입 니 다.

densityDpi:480
density:3.0
getByteCount()소스 코드 를 통 해 알 수 있 듯 이 Bitmap.getByteCount()는:
(bitmapWidth*scale)*(bitmapHeight*scale)*(픽 셀 당 바이트 크기)에서 나 온
그 중:int scale=phoneDensity/inDensity
phone Density 는 우리 핸드폰 의 density Dpi 입 니 다.상술 한 바 와 같이 제 핸드폰 은 480 입 니 다.
inDensity 는 그림 을 저장 하 는 경로 입 니 다.예 를 들 어 xhdpi 는 320 이 고 xhdpi 는 480 입 니 다.
BitmapFactory 기본 색상 은 ARGB8888 그림,픽 셀 당 4 bytes 차지
xhdpi 에서:200*(480/320)*200(480/320)4=360000
xxhdpi 에서:200*(480/480)*200(480/480)4=160000
이상 은 bitmap 가 차지 하 는 메모리 분석 입 니 다.
2.고 효율 로드
1.bitmap.config 수정
2.inSampleSize 수정
bitmap.config 프로필
위 에서 언급 한 BitmapFactory 의 기본 색상 도 는 ARGB 입 니 다.8888
Bitmap.Config 는 모두 네 개의 인자 가 다음 과 같 습 니 다.
(이 매개 변 수 는 Bitmap 비트 맵 의 설정 을 결정 합 니 다.bitmap 의 픽 셀 이 어떻게,색채,투명 성 이 있 는 지 에 영향 을 줄 수 있 습 니 다)
Bitmap.Config ALPHA_8
이 매개 변 수 는 픽 셀 마다 1 바이트 의 공간 을 차지한다.
이것 은 모든 픽 셀 점 이 하나의 투명도 로 저 장 된 채널 을 대표 합 니 다.이것 은 마스크 를 설정 하 는 그림 의 용례 에 매우 유용 하고 색상 정 보 를 저장 하지 않 습 니 다.
Bitmap.Config RGB_565
이 매개 변 수 는 픽 셀 마다 2 바이트 의 공간 을 차지한다.
이것 은 RGB 채널 만 있 는 인 코딩 을 대표 하 는데 빨간색 은 5 개의 주 소 를 차지 하고 녹색 은 6 개의 주 소 를 차지 하 며 파란색 은 5 개의 주 소 를 차지한다.투명 성 이 없 는 통로.
불투명 한 비트 맵 을 사용 할 때 높 은 색상 보 정 도 를 요구 하지 않 고 이 설정 을 사용 하 는 것 이 좋 습 니 다.
Bitmap.Config ARGB_4444
이 매개 변 수 는 픽 셀 마다 2 바이트 의 공간 을 차지한다.
그것 은 모두 네 개의 통로 가 있 는데 말 그대로 투명도,빨간색,녹색,파란색 이다.채널 마다 각각 네 개의 주 소 를 차지 하기 때문에 모두 2 바이트 입 니 다.
응용 프로그램 이 메모리(색채 품질 에 대한 요구 가 낮 음)를 절약 하 는 동시에 투명 도 정 보 를 저장 해 야 합 니 다.이 설정 은 선택 할 수 있 지만 공식 적 으로 ARGB 를 사용 하 는 것 을 추천 합 니 다.8888 의 설정 은 색채 의 질 이 떨 어 지기 때 문 입 니 다.
Bitmap.Config ARGB_8888
이 매개 변 수 는 픽 셀 마다 4 바이트 의 공간 을 차지한다.
이것 도 모두 4 개의 채널 이지 만 다른 것 은 각 채널 역 의 8 개의 주소 이기 때문에 색채 의 질 이 이전 설정 보다 특히 높다(16 배).
가장 좋 은 비트 맵 품질 을 만족 시 킬 수 있 습 니 다.메모리 가 충분 한 상황 에서 이 걸 사용 하 는 것 을 추천 합 니 다.
inSampleSize 안내
BitmapFactory.Options 를 통 해 그림 의 크기 를 조정 합 니 다.주로 inSampleSize 매개 변 수 를 사용 합 니 다.inSampleSize=1 일 때 샘플링 한 그림 은 그림 의 원본 크기 입 니 다.inSampleSize=2 일 때 샘플링 한 그림 의 너비,높이 는 모두 원 그림 크기 의 1/2 이 고 픽 셀 수 는 원 그림 의 1/4 이 며 그림 의 원래 메모리 가 4MB 라 고 가정 합 니 다.만약 에 inSampleSize 를 2 로 설정 하면...메모리 가 1MB 가 됩 니 다.
구체 적 인 실현 코드 는 다음 과 같다.

 public static Bitmap decodeBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight){
  final BitmapFactory.Options options=new BitmapFactory.Options();
  options.inJustDecodeBounds=true;
  BitmapFactory.decodeResource(res,resId,options);
  options.inSampleSize=1;
  options.inSampleSize=setInSampleSize(options,reqWidth,reqHeight);
  options.inPreferredConfig= Bitmap.Config.ARGB_4444;
  options.inJustDecodeBounds=false;
  return BitmapFactory.decodeResource(res,resId,options);
 }

 public static int setInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight){
  final int height=options.outHeight;
  final int width=options.outWidth;
  int inSampleSize=1;
  if(height>reqHeight||width>reqHeight){
   final int halfHeght=height/2;
   final int halfWidht=width/2;
   while ((halfHeght/inSampleSize>=reqHeight)&&(halfWidht/inSampleSize>=reqWidth)){
    inSampleSize *=2;
   }
  }
  return inSampleSize;
 }

위의 두 가지 방법 이 있 으 면 실제 사용 은 간단 합 니 다.예 를 들 어 imageView 가 원 하 는 그림 의 크기 는 100 X 100 입 니 다.이때 우 리 는 이렇게 호출 할 수 있 습 니까?아니면 이전에 xx hdpi 에 저 장 된 그림 입 니까?상기 코드 에서 bitmap.config 를 ARGB 로 설정 하 였 습 니 다.4444,지금 원래 사이즈 200 X 200 을 100 X 100 으로 바 꾸 고 메모리 가 얼마 인지 보 세 요.

Bitmap bitmap=
decodeBitmapFromResource(getResources(),R.mipmap.btn_go,100,100);
Log.i(TAG,bitmap.getByteCount()+"");
bitmap.getByteCount 의 출력 결 과 는 20000 으로 이전 160000 보다 8 배 줄 었 고 ARGB4444 비교 ARGB8888 은 2 배 줄 어 들 고 사 이 즈 를 100 으로 설정 하여 setInSampleSize()방법 에 들 어가 inSampleSize=2 를 얻 었 습 니 다.픽 셀 수 는 원 그림 의 1/4 이 고 메모리 크기 는 모두 이전의 1/8 이 되 었 습 니 다.이렇게 하면 효율 적 인 그림 을 불 러 오 면 oom 에서 멀 어 집 니 다.

좋은 웹페이지 즐겨찾기