4

현재 메신저는 SD 카드에서 이미지를 표시하는 앱을 만듭니다. 기본적으로 MediaStore 피커의 카메라에서 앨범을 만들고 사진을 추가합니다. 뷰를 이미지 갤러리 (로컬 이미지)를 구현하는 방법

  • 내가 그나마
  • 그리드 뷰를 표시 할 사용자 정의 PagerAdapter있는 viewpager를 반환하는 사용자 정의 BaseAdapter와

    1. 표준 갤러리 응용 프로그램 :

      나는이 방법을 구현하는 시도 따라서 전체 화면으로 바로 이동해야합니다. 그 후 왼쪽과 오른쪽으로 스 와이프를 비활성화하고 클릭 만 듣고 싶습니다.

      atm 두 가지 방법 모두 세로 모드에서 작동합니다. 내가 풍경으로 전환 할 때 일부 이미지는

      03-20 12:20:56.515: W/OpenGLRenderer(17398): Bitmap too large to be uploaded into a texture 
      

      메모리 부족 오류 다음에 놓습니다. OOM 및 갤러리에 대한 문제가 가득 찼을 경우 스택 오버플로가 발생하면 convertView가 BaseAdapter의 getView에서 항상 null이므로보기가 작동하도록보기를 재사용해야합니다.

      그래서 리사이클러를 뷰에 사용했고, 뷰를 2 개로 제한했으며 초상화 모드는 방법 1 (갤러리 사용)에서 작동했습니다. 풍경은 여전히 ​​나에게 같은 문제를 준다. 방법 2의

      은 (viewflipper)는 그러나 세로 모드는 여기서 일하는 ... 느릅 나무가 BTW 호출되지 않습니다

      @Override 
      public void destroyItem(ViewGroup container, int position, Object object) { 
      

      로 의견을 처리합니다. 풍경이 여전히 충돌합니다.

      비트 맵 얻기위한 나의 방법 : 내 이미지 뷰가 여전히 크기 (0,0) 내가 그것을 팽창 할 때이기 때문에

      public static Bitmap getBitmap(Context ctx, int imageId, ImageView target) { 
      
          String file = getPath(ctx, imageId); 
      
          BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
          bmOptions.inJustDecodeBounds = true; 
      
          BitmapFactory.decodeFile(file, bmOptions); 
          WindowManager mgr = (WindowManager)   ctx.getSystemService(Context.WINDOW_SERVICE); 
      
          int scaleFactor = 1; 
      
          if (mgr != null) { 
           // Get the dimensions of the View 
           int targetW = mgr.getDefaultDisplay().getWidth(); 
           int targetH = mgr.getDefaultDisplay().getHeight(); 
           Log.d(TAG, "Image width + height=" + targetW + "," + targetH); 
      
      
           int photoW = bmOptions.outWidth; 
           int photoH = bmOptions.outHeight; 
           // Determine how much to scale down the image 
           scaleFactor = Math.min(photoW/targetW, photoH/targetH); 
      
          } else { 
           Log.d(TAG, "Target is null"); 
          } 
      
          // Get the dimensions of the bitmap 
          // Decode the image file into a Bitmap sized to fill the View 
          bmOptions.inJustDecodeBounds = false; 
          bmOptions.inSampleSize = scaleFactor; 
          bmOptions.inPurgeable = true; 
          logHeap(ImageHelper.class); 
      
          Bitmap bm = BitmapFactory.decodeFile(file, bmOptions); 
      
          if (target != null) { 
           target.setImageBitmap(bm); 
          } 
          return bm; 
      } 
      

      잘 작동

      , 내가이 화면 크기를 얻을 수있는 창 관리자를 사용하여 알고 있지만 그입니다 . 그 후 나는

      내가 드로어 블을 사용하지 말아 또는 기타 자원이 APK에 포함되어 있습니다 ...

      imgView.setLayoutParams(new Gallery.LayoutParams(
            Gallery.LayoutParams.FILL_PARENT, 
            Gallery.LayoutParams.FILL_PARENT)); 
          imgView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 
      

      아무것도가 작동하는 것 같다 호출합니다. 이 갤러리는 SD 카드 나 카메라에서 촬영 한 품질로 사진을로드 할 수 있어야합니다. obvously 갤러리는 디렉터리에있는 것처럼 많은 이미지를 처리 ​​할 수 ​​있어야합니다.

      다음 질문으로 나를 도와 줄 수 있습니까?

      1. 기본 갤러리를 전체 화면으로 바로 이동하고 격자보기를 차단할 수있는 방법이 있습니까? 이 방법은 내보기를 만드는 대신 이미지를 제공하는 어댑터 만 있으면됩니다. (아마도 이것은 OOM 충돌을 해결할 것입니다)
      2. 내 비트 맵 디코딩 기능이 정상입니까? 나는 풍경의 변화를 잡기 위해 해킹을 할 필요가 있습니까?
      3. 뷰어 갤러리 나 갤러리를 사용하여 필요한 갤러리를 만드는 가장 좋은 방법은 무엇입니까?
      4. 누구나 충돌하지 않는 전체 화면 갤러리의 샘플 코드가 있습니까?
    +0

    갤러리를 만들거나 갤러리에 액세스하려고합니까? 또한 디코드 로직도 괜찮아 보입니다. – lokoko

    답변

    1

    이것은 과거에 몇 번이나 겪었던 문제입니다. Google은 실제로 이에 관한 기사를 게시했습니다.

    문제는 inSampleSize에서 이미지를 디코딩하는 데 사용됩니다. 서로 다른 장치에는 화면과 메모리 크기가 다르기 때문에 (VM 힙 크기가 12에서 64 이상이 될 수 있음) 모든 이미지에서 동일한 방식으로 이미지를 디코딩 할 수 없습니다. 예를 들어 12Mb 힙 메모리가있는 320x240 장치의 이미지는 주어진 inSampleSize이고 1280x720 64Mb 힙 메모리 장치는 다른 inSampleSize (더 큰 이미지)를 사용자가 사용해야합니다.

    기사 i 공격은 주어진 높이와 너비의 이미지를 효율적으로 렌더링하는 방법을 보여줍니다. 마지막 코드 세그먼트에 특별한주의를 기울여 파일을 미리 열어두고 나중에 "전체 디코드"를 위해 inSampleSize를 계산합니다.

    이 권장 사항을 추가하고 싶습니다.

    1. 는 SD를 사용하는 시간이 걸리고이 응용 프로그램이 느린, 중단 될 수과를 줄 것이기 때문에이 작업이 완료 (새로운 스레드 나 AsyncTask를 전화, 비동기 방식으로 "getBitmap"기능을 사용하여 중급 저가 장치에 나쁜 인상을주었습니다.

    2. "Bitmap bitmap = new Bitmap()"을 여러 개 만들지 마십시오.로드 된 비트 맵은 RAM에 저장되고 한 번 할당됨을 인식해야합니다. 가비지 컬렉터가 가져올 수있는 "힘들어하는"관점보기.

    3. Bitma 사용을 마쳤 으면 p over를 null로 만듭니다. 이것은 당신이 12Mb 최대 힙 RAM을 가지고 있다고 상상해보십시오. 귀하의 애플 리케이션은 지금 8Mb를 사용하고 있습니다. 가비지 컬렉터가 시작되고 더 이상 사용되지 않는 RAM을 얻지 못합니다. 당신은 ImageView에 데이터를 할당 한 후에 10 비트 맵을 빨리 만들지 않고 어떻게 든 참조를 유지합니다. 각 비트 맵에서 500Kb 램을 사용하면 앱이 다운됩니다. 사용 후 항상 비트 맵을 null로 만듭니다.

    4. 마지막으로 Google 플랫폼 도구에서 제공하는 DDMS를 사용하십시오 (디버그를 위해 이클립스에 액세스 할 수 있으며 메모리 사용량을 볼 수 있으며 가비지 수집을 통해 앱의 동작을 볼 수도 있습니다).