2014-11-14 2 views
2

Android 개발을 처음 사용했습니다. HTTP를 통해 이미지를 다운로드하고 ImageViews 또는 Drawables 안에 이미지를 저장하려고합니다. 이 예제에서는 ImageViews를 사용하고 있습니다. 처음에는 AsyncTask를 사용하여 이미지를 다운로드했는데 (약 500KB 정도), 피카소를 사용하기로 결정했다.Android Picasso ImageView - 메모리 부족 예외 MemoryLeak

아래 코드에는 20 개의 ImageView가 있습니다. 각각의 이미지 URL은 약 400KB의 이미지입니다. 그러나 모두로드 한 후 getUsedMem()이 100MB보다 큽니다. 나는이 메모리 누출의 원인을 잘 모릅니다.

저를 도와 주시겠습니까?

public class Example extends Activity { 
    public long getUsedMem() 
    { 
     long freeSize = 0L; 
     long totalSize = 0L; 
     long usedSize = -1L; 
     try { 
      Runtime info = Runtime.getRuntime(); 
      freeSize = info.freeMemory(); 
      totalSize = info.totalMemory(); 
      usedSize = totalSize - freeSize; 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     return usedSize; 
    } 

    public void concatLogMessages(String msg) 
    { 
     TextView tv = (TextView) findViewById(R.id.textView1); 
     CharSequence cs = tv.getText(); 

     tv.setText(cs + "\n" + 
        "Image #: " + msg + "\n" + 
        "Used Mem: " + getUsedMem() 
        ); 
    } 

    public void loadImage(final ImageView target, String url, final int num) { 
     Picasso.with(this).load(url).into(target, new EmptyCallback(){ 
      @Override 
      public void onError() { 
       Example.this.concatLogMessages("Picasso onError"); 
       super.onError(); 
      } 

      @SuppressLint("NewApi") @Override 
      public void onSuccess() { 
       Example.this.concatLogMessages("Picasso onSuccess " + num); 
       super.onSuccess(); 
      } 
     }); 
    } 

    @SuppressLint("NewApi") 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     drawables = new ArrayList<Drawable>(); 

     // Check Memory Before Everything 
     concatLogMessages("0"); 

     // Imageview to show 
     ImageView image1 = (ImageView) findViewById(R.id.imageView1); 
     ImageView image2 = (ImageView) findViewById(R.id.imageView2); 
     ImageView image3 = (ImageView) findViewById(R.id.imageView3); 
     ImageView image4 = (ImageView) findViewById(R.id.imageView4); 
     ImageView image5 = (ImageView) findViewById(R.id.imageView5); 
     ImageView image6 = (ImageView) findViewById(R.id.imageView6); 
     ImageView image7 = (ImageView) findViewById(R.id.imageView7); 
     ImageView image8 = (ImageView) findViewById(R.id.imageView8); 
     ImageView image9 = (ImageView) findViewById(R.id.imageView9); 
     ImageView image10 = (ImageView) findViewById(R.id.imageView10); 
     ImageView image11 = (ImageView) findViewById(R.id.imageView11); 
     ImageView image12 = (ImageView) findViewById(R.id.imageView12); 
     ImageView image13 = (ImageView) findViewById(R.id.imageView13); 
     ImageView image14 = (ImageView) findViewById(R.id.imageView14); 
     ImageView image15 = (ImageView) findViewById(R.id.imageView15); 
     ImageView image16 = (ImageView) findViewById(R.id.imageView16); 
     ImageView image17 = (ImageView) findViewById(R.id.imageView17); 
     ImageView image18 = (ImageView) findViewById(R.id.imageView18); 
     ImageView image19 = (ImageView) findViewById(R.id.imageView19); 
     ImageView image20 = (ImageView) findViewById(R.id.imageView20); 

     /* Picasso */ 
     ImageView target = (ImageView) findViewById(R.id.picassoImageView); 

     loadImage(target, image_url1, 0); 

     // Test 1-20 image views... 
     loadImage(image1, R.String.image_url1, 1); 
     loadImage(image2, R.String.image_url2, 2); 
     loadImage(image3, R.String.image_url3, 3); 
     loadImage(image4, R.String.image_url4, 4); 
     loadImage(image5, R.String.image_url5, 5); 
     loadImage(image6, R.String.image_url6, 6); 
     loadImage(image7, R.String.image_url7, 7); 
     loadImage(image8, R.String.image_url8, 8); 
     loadImage(image9, R.String.image_url9, 9); 
     loadImage(image10, R.String.image_url10, 10); 
     loadImage(image11, R.String.image_url11, 11); 
     loadImage(image12, R.String.image_url12, 12); 
     loadImage(image13, R.String.image_url13, 13); 
     loadImage(image14, R.String.image_url14, 14); 
     loadImage(image15, R.String.image_url15, 15); 
     loadImage(image16, R.String.image_url16, 16); 
     loadImage(image17, R.String.image_url17, 17); 
     loadImage(image18, R.String.image_url18, 18); 
     loadImage(image19, R.String.image_url19, 19); 
     loadImage(image20, R.String.image_url20, 20); 
    } 
} 
+0

보기 [이]가 (http://stackoverflow.com/questions/477572/) –

답변

5

누출이라고 생각하지 않습니다.

Android에서 이미지를 '펼칩니다'(즉 비트 맵으로 디코딩하면) 픽셀 당 4 바이트를 사용합니다. 픽셀 수를 세고, 4를 곱한 다음 20 (이미지 수)를 곱하면 100MB의 수치에 가까워집니다. 예를 들어 이미지의 해상도가 1,000,000 픽셀 인 경우 1,000,000 x 4 x 20 = 80mb가됩니다.

이미지를 한꺼번에로드하지 않아야합니다. 어떤 종류의 LRU 캐시 또는 유사하게 (또는 캐싱을 처리하는 유니버설 이미지 로더 라이브러리를 사용하십시오.) 필요할 때만 비트 맵을로드하십시오. http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

+0

이 정보를 주셔서 대단히 감사합니다. LRU 캐시 알고리즘을 살펴보고 읽어 들일 것입니다. 다른 캐시 알고리즘보다 LRU를 권장 할 의향이 있습니까? 또한 유니버설 이미지 로더에 대한 권장 사항이 있습니까? Picasso는 불가능합니까? Volley 라이브러리는 적합합니까? – codeshark

+0

이 라이브러리를 참조하고 있습니다 : https://github.com/nostra13/Android-Universal-Image-Loader. 사용하기가 매우 쉽고 다양한 종류의 캐싱을 처리 할 수 ​​있습니다. d는 자신에게 URI (파일 위치 등)를 제공하지만 나머지는 사용자를 위해 처리해야합니다. 또한 고도로 구성 가능합니다. – kha

1

나는 이미지의 많은이를 사용하고 있는데 잘 작동

private class LoadImage extends AsyncTask<String, String, Bitmap> { 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
     pDialog = new ProgressDialog((Main)context); 
     pDialog.setMessage("Loading Image ...."); 
     pDialog.show(); 
    } 
    protected Bitmap doInBackground(String... args) { 
      Log.i("doInBack 1","length = 1 "); 
      try { 
       Bitmap positivo = BitmapFactory.decodeStream((InputStream)new URL(args[0]).getContent()); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

     return positivo; 
    } 
    protected void onPostExecute(Bitmap image) { 
     if(image != null){ 
      //*bitmap is the bitmap u change each time 
      bitmap = image; 
      invalidate(); 
      pDialog.dismiss(); 
     } 
    } 

이를 호출하는 방법을? u는 단지 URL

new LoadImage().execute("https://yourimage.jpg"); 
으로 이미지를 변경하려면이 쓰기
+0

이 안드레스 주셔서 감사합니다 :

은 내가보기 엔이 기사를 읽고 매우 밀접하게 조언을 다음 좋습니다. 하나의 액티비티에서 20 개의 ImageView 항목을 20 번 실행하면 사용 된 메모리가 많이 증가할까요? – codeshark

+0

동시에 20 개의 이미지가 필요합니까? –

+0

예 : (사용 메모리 약 120MB가 표시됩니다. – codeshark