내 응용 프로그램에 따르면 먼저 내 리소스의 모든 이미지를 내부 메모리로 복사 한 다음 Image Slide에서 왼쪽 또는 오른쪽으로 인덱스의 메모리에서 이미지를 가져 와서 보여줍니다. . 그리고 저는 AsynTask로이 작업을하고 있습니다. 약 10 개의 이미지가 표시되면 응용 프로그램이 검은 색 화면으로 바뀌고 로그 고양이가 "이 프로세스에 너무 큰 외부 할당"이라고 표시됩니다. 여기에서 읽은 것들에 따르면 문제는 AsyncTask에 관한 것이라고 생각합니다.이 작업에 사용 된 메모리를 해제 할 수 없습니다. 나는 이미지를 갤러리로 보여주는 데 사용되는 세 가지 다른 액티비티를 가지고 있으며, 각각의 액티비티는 asyncTask를 사용하여 이미지를 보여줍니다.안드로이드에서 AsyncTask 및 메모리 부족 문제가 발생했습니다.
아래 코드 중 일부는 도움이 될 것입니다. 미리 감사드립니다. 여기 내 이미지는 슬라이딩 이미지에 따라 이미지 다운로더를 실행하는 데 사용됩니다.
lid1 = new LocalImageDownloader(imageSwitcher, myContext, path, nameList.get(curIndex));
lid1.execute();
imageSwitcher.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
downX = (int) event.getX();
Log.i("event.getX()", " downX " + downX);
return true;
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
upX = (int) event.getX();
Log.i("event.getX()", " upX " + downX);
if (upX - downX > 100) {
//curIndex current image index in array viewed by user
curIndex--;
if (curIndex < 0) {
curIndex = imageList.size()-1;
}
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide_in_left));
imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide_out_right));
lid1.cancel(true);
lid1 = new LocalImageDownloader(imageSwitcher, myContext, path, nameList.get(curIndex));
lid1.execute();
}
else if (downX - upX > -100) {
curIndex++;
if (curIndex == imageList.size()) {
curIndex = 0;
}
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide_in_right));
imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide_out_left));
lid1.cancel(true);
lid1 = new LocalImageDownloader(imageSwitcher, myContext, path, nameList.get(curIndex));
lid1.execute();
}
return true;
}
return false;
}
});
이 내부 메모리에서 이미지를 얻을 내 AsyncTask를하고,
public class LocalImageDownloader extends AsyncTask<String, Void, Bitmap> {
String url;
Drawable d;
Context myContext;
String path;
String fileName;
ProgressDialog dialog;
int REQUIRED_SIZE=600;
private final WeakReference<ImageSwitcher> imageViewReference;
public LocalImageDownloader(ImageSwitcher imageSwitcher,Context myContext, String path, String fileName) {
this.myContext = myContext;
this.path = path;
this.fileName = fileName;
imageViewReference = new WeakReference<ImageSwitcher>(imageSwitcher);
}
@Override
protected Bitmap doInBackground(String... urls) {
publishProgress();
return null;
}
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(myContext, "", "Loading Images...", true);
super.onPreExecute();
}
@Override
protected void onPostExecute(Bitmap result) {
try {
if (imageViewReference != null) {
ImageSwitcher imageSwitcher = imageViewReference.get();
if (imageSwitcher != null) {
imageSwitcher.setImageDrawable(getLocalImage());
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dialog.dismiss();
}
public Drawable getLocalImage() throws IOException {
File file = new File(path,fileName);
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file),null,o);
//The new size we want to scale to
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=this.REQUIRED_SIZE && o.outHeight/scale/2>=this.REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
o.inJustDecodeBounds = false;
return new BitmapDrawable(BitmapFactory.decodeStream(new FileInputStream(file), null, o2));
}
}
편집 : 나는 더 효율적으로 비트 맵을 사용하는 몇 가지 방법을 적용하고 지금은 그들을 밀어있어 메모리에 있지만 거의 동일한 오류가 있습니다. 이미지 중 일부가 메모리에 저장되고 이미지의 일부가 검은 색 화면으로 표시되고 같은 오류가 발생합니다. "외부 할당이 너무 많습니다." 어떤 생각을하는 방법?
아래 메모리 캐시 코드는 다음과 같습니다. MemoryCache 개체를 매개 변수로 AsyncTask에 보냅니다.
public class MemoryCache {
private static final String TAG = "MemoryCache";
private Map<String, Bitmap> cache=Collections.synchronizedMap(
new LinkedHashMap<String, Bitmap>(10,1.5f,true));//Last argument true for LRU ordering
private long size=0;//current allocated size
private long limit=1000000;//max memory in bytes
public MemoryCache(){
//use 50% of available heap size
setLimit(Runtime.getRuntime().maxMemory()/2);
}
public void setLimit(long new_limit){
limit=new_limit;
Log.i(TAG, "MemoryCache will use up to "+limit/1024./1024.+"MB");
}
public Bitmap get(String id){
try{
if(!cache.containsKey(id))
return null;
//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
return cache.get(id);
}catch(NullPointerException ex){
return null;
}
}
public void put(String id, Bitmap bitmap){
try{
if(cache.containsKey(id))
size-=getSizeInBytes(cache.get(id));
cache.put(id, bitmap);
size+=getSizeInBytes(bitmap);
checkSize();
}catch(Throwable th){
th.printStackTrace();
}
}
private void checkSize() {
Log.i(TAG, "cache size="+size+" length="+cache.size());
if(size>limit){
Iterator<Entry<String, Bitmap>> iter=cache.entrySet().iterator();//least recently accessed item will be the first one iterated
while(iter.hasNext()){
Entry<String, Bitmap> entry=iter.next();
size-=getSizeInBytes(entry.getValue());
iter.remove();
if(size<=limit)
break;
}
Log.i(TAG, "Clean cache. New size "+cache.size());
}
}
public void clear() {
cache.clear();
}
long getSizeInBytes(Bitmap bitmap) {
if(bitmap==null)
return 0;
return bitmap.getRowBytes() * bitmap.getHeight();
}
public boolean contains(String key) {
if(cache.containsKey(key)) {
return true;
}
return false;
}
}
어떻게 메모리를 관리합니까 ??? –
나는 그것에 대해 살펴 보지 못했지만 이미지를 메모리에로드하는 대신 이미지를 슬라이드 할 때마다 입력 스트림에서 이미지를 가져 오는 것만 같다고 생각합니다. 메모리에있는 것보다 훨씬 빠르기 때문입니다. – osayilgan