2012-07-26 5 views
1

이것은 Android 질문보다 Java 질문 일 수 있지만 AsyncTask 내에서 작성된 Bitmap을 검색하여 다른 클래스 (활동)에 저장하는 데 어려움이 있습니다. 내가 그것을 사용할 때 그것을 재활용 할 수 있습니다.AsyncTask 내에서 새 비트 맵 참조 설정하기

AsyncTask는 doInBackground()에 비트 맵을 만들고 onPostExecute()에서 ImageView의 비트 맵으로 설정합니다.이 이미지 뷰는 생성자를 통해 전달됩니다. 그러나 완료 후에는 활동에서 비트 맵에 액세스 할 수 있어야합니다. 액티비티에는 ImageView와 다른 비트 맵의 ​​ArrayList가 있지만 AsyncTask는 새로운 비트 맵을 생성하므로 액티비티의 비트 맵 ArrayList에서이 새 객체를 쉽게 찾을 수 없습니다. 현재 나는 AsyncTask 생성자에 대한 목록에있는 인덱스와 함께 ArrayList를 전달하여 작업을 수행하고 있으며 doInBackground는 배열의 해당 항목을 새로 만든 비트 맵으로 설정합니다.

나는 액티비티가 비트 맵의 ​​ArrayList를 가지고 있지 않은 다른 것들에 대해이 AsyncTask를 사용할 수 있기를 원하기 때문에이 솔루션을 좋아하지 않는다. 자바가 값에 의한 참조를 전달하고 새로운 Bitmap 객체로 설정하면 호출자에 대한 액세스가 허용되지 않기 때문에 AsyncTask 생성자에 비트 맵을 단순히 제공 할 수 없습니다.

더 우아하게 어떻게 할 수 있습니까?

다음은 관련 코드입니다. 이 질문과 관련이없는 라인은 명확하게하기 위해 생략되었습니다. 여기

public class LoadCachedImageTask extends AsyncTask<String, Void, Void> { 
    private Context context; 
    private ImageView image; 
    private ArrayList<Bitmap> bitmaps; 
    int index; 

    public LoadCachedImageTask(Context context, ImageView image, ArrayList<Bitmap> bitmaps, int index) { 
     this.context = context; 
     this.image = image; 
     this.bitmaps = bitmaps; 
     this.index = index; 
    } 

    protected Void doInBackground(String... urls) { 
     String url = urls[0]; 
     Bitmap bitmap = null; 

     // Create the bitmap 
     File imageFile = new File(context.getCacheDir(), "test"); 
     bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath()); 

     // Set the bitmap to the bitmap list 
     bitmaps.set(index, bitmap); 

     return null; 
    } 

    protected void onPostExecute(Void arg) { 
     // Display the image 
     image.setImageBitmap(bitmaps.get(index)); 
    } 

    protected void onCancelled() { 
     if (bitmaps.get(index) != null) { 
      bitmaps.get(index).recycle(); 
      bitmaps.set(index, null); 
     } 
    } 
} 

그리고

그것을 사용하는 샘플 작업입니다.

public class SampleActivity extends Activity { 
    private ArrayList<ImageView> images; 
    private ArrayList<Bitmap> bitmaps; 

    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     images = new ArrayList<ImageView>(); 
     bitmaps = new ArrayList<Bitmap>(); 
     int numImages = 15; 

     // Create the images and bitmaps 
     for (int i = 0; i < numImages; i++) { 
      images.add(new ImageView(this)); 
      bitmaps.add(null); 
     } 

     // Load the bitmaps 
     for (int i = 0; i < numImages; i++) { 
      new LoadCachedImageTask(this, images.get(i), bitmaps, i).execute("http://random.image.url"); 
     } 
    } 
} 

위의 코드를 테스트하지 않았으므로 작동하지 않을 수 있습니다.

답변

1

많은 수의 비트 맵을 비동기 적으로 많은 수의 ImageViews에로드하려고합니다. 각 ImageView에 대해 여러 번 사용하는 단일 AsyncTask 클래스로이 작업을 수행 할 수 있다고 생각합니다.

for(ImageView imgView : images) { 
    (new LoadCachedImageTask<String, Void, Bitmap>)(imgView).execute(getBitmapUrl()); 
} 

에 대한 루프 각 ImageView 참조를 통해 반복됩니다

public class LoadCachedImageTask extends AsyncTask<String, Void, Bitmap> { 
    private final WeakReference<ImageView> mImgView; 

    public LoadCachedImageTask(ImageView image) { 
     mImageView = new WeakReference<ImageView>(image); 
    } 

    protected Void doInBackground(String... urls) { 
     if(urls == null || urls.length < 1) 
     return; 

     // Create the bitmap 
     final Bitmap bitmap = BitmapFactory.decodeFile(url); 

     return bitmap; 
    } 

    protected void onPostExecute(Bitmap bmp) { 
     // Display the image 
     if(bmp != null) { 
     final ImageView imageView = (ImageView) mImgView.get(); 
     if(imageView != null) // needed in case the weakreference is removed 
      imageView.setImageBitmap(bmp); 
    } 
} 

다음과 같이 뭔가 ImageViews의 배열을 채우기 위해 :

당신은 AsyncTask 이런 식으로 뭔가해야 것 그리고 그것을 아주 새로운 AsyncTask 참조로 보내주십시오. 그러면 필요한 비트 맵에 대해 지정된 URL로 AsyncTask를 실행합니다. asynctask는 ImageView가 존재하는 한 ImageView의 참조를 유지합니다. 어떤 이유로 ImageView가 손상된 경우에도 비트 맵은 계속로드되어 즉시 버려집니다.

+0

ImageView로 설정 한 후 Bitmap을 직접 재활용하고 있습니다. ImageView를 그릴 때 문제가 발생하지 않습니까? – may5694

+0

비트 맵이 ImageView에 복사 된 것으로 생각합니다. 재활용에 영향을 미치지 않도록 자체 스케일링 메커니즘이 내장되어 있기 때문입니다. 이제는 언급 했으니 까. 내 개인 코드 중 어느 것도이 작업을 수행하지 않습니다. 그래도 문제가 해결되지 않으면 알려 주시고 편집하겠습니다. – DeeV

+0

몇 가지 테스트를 해봤는데 현재 ImageView에서 사용되는 Bitmap을 재활용하면 java.lang.RuntimeException : Canvas : recycled bitmap을 사용하게됩니다. 이것이 실제로 비트 맵 참조를 고수해야하는 이유입니다. 따라서 메모리를 저장하고 사용하는 데 익숙해지면 다시 사용할 수 있습니다. – may5694

관련 문제