Android中的异步任务和内存不足问题

Android中的异步任务和内存不足问题,android,asynchronous,bitmap,android-asynctask,Android,Asynchronous,Bitmap,Android Asynctask,根据我的应用程序,首先我将所有图像从我的资源复制到内存中,然后在图像幻灯片上向左或向右,我从内存中获取图像及其索引,并在那里显示。我正在用AsynTask做这件事。在显示了大约10幅图像后,应用程序进入黑屏,log cat说“外部分配对于这个过程来说太大了。”根据我在这里读到的内容,我认为问题在于AsyncTask,我无法释放用于这些任务的内存。 我有三个不同的活动,用于将图像显示为图库,每个活动都使用asyncTask来显示图像 下面是我的一些代码,任何帮助都将不胜感激,提前谢谢。 下面是我的

根据我的应用程序,首先我将所有图像从我的资源复制到内存中,然后在图像幻灯片上向左或向右,我从内存中获取图像及其索引,并在那里显示。我正在用AsynTask做这件事。在显示了大约10幅图像后,应用程序进入黑屏,log cat说“外部分配对于这个过程来说太大了。”根据我在这里读到的内容,我认为问题在于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;
                }
            });
lid1=newlocalimagedownloader(imageSwitcher、myContext、path、nameList.get(curIndex));
lid1.execute();
setOnTouchListener(新的OnTouchListener(){
公共布尔onTouch(视图v,运动事件){
if(event.getAction()==MotionEvent.ACTION\u向下){
downX=(int)event.getX();
Log.i(“event.getX()”,“downX”+downX);
返回true;
} 
else if(event.getAction()==MotionEvent.ACTION\u UP){
upX=(int)event.getX();
Log.i(“event.getX()”,“upX”+downX);
如果(上行-下行>100){
//curIndex用户查看的数组中的当前图像索引
库林德斯--;
if(curIndex<0){
curIndex=imageList.size()-1;
}
imageSwitcher.setinaimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide在左)中);
imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide_out_right));
lid1.取消(true);
lid1=新的LocalImageDownloader(imageSwitcher、myContext、path、nameList.get(curIndex));
lid1.execute();
}
否则如果(向下-向上>-100){
curIndex++;
if(curIndex==imageList.size()){
curIndex=0;
}
imageSwitcher.setInAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide在右方));
imageSwitcher.setOutAnimation(AnimationUtils.loadAnimation(Activities.this,R.anim.slide_out_left));
lid1.取消(true);
lid1=新的LocalImageDownloader(imageSwitcher、myContext、path、nameList.get(curIndex));
lid1.execute();
}
返回true;
}
返回false;
}
});
这是我从内存中获取图像的任务

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));
}

}
公共类LocalImageDownloader扩展异步任务{
字符串url;
可抽出式d;
语境;
字符串路径;
字符串文件名;
进程对话;
所需的int_大小=600;
私有最终WeakReference imageViewReference;
公共LocalImageDownloader(ImageSwitcher ImageSwitcher、上下文myContext、字符串路径、字符串文件名){
this.myContext=myContext;
this.path=path;
this.fileName=文件名;
imageViewReference=新的WeakReference(图像切换器);
}
@凌驾
受保护位图doInBackground(字符串…URL){
出版进度();
返回null;
}
@凌驾
受保护的void onPreExecute(){
dialog=ProgressDialog.show(myContext,“,”正在加载图像…”,true);
super.onPreExecute();
}
@凌驾
受保护的void onPostExecute(位图结果){
试一试{
if(imageViewReference!=null){
ImageSwitcher ImageSwitcher=imageViewReference.get();
if(图像切换器!=null){
setImageDrawable(getLocalImage());
}
}
}catch(filenotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
dialog.dismise();
}
公共可绘制getLocalImage()引发IOException{
文件=新文件(路径、文件名);
//解码图像大小
BitmapFactory.Options o=新的BitmapFactory.Options();
o、 inJustDecodeBounds=true;
decodeStream(新文件输入流(文件),null,o);
//我们要扩展到的新尺寸
//找到正确的刻度值。它应该是2的幂。
int标度=1;
而(o.outWidth/scale/2>=此.REQUIRED\u尺寸和&o.outHeight/scale/2>=此.REQUIRED\u尺寸)
比例*=2;
//用inSampleSize解码
BitmapFactory.Options o2=新的BitmapFactory.Options();
o2.inSampleSize=刻度;
o、 不公正=错误;
返回新的BitmapDrawable(BitmapFactory.decodeStream(新文件输入流(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;
}
公共类内存缓存{
私有静态最终字符串TAG=“MemoryCache”;
私有映射缓存=Collections.synchronizedMap(
新LinkedHashMap(10,1.5f,真
ImageView imageView = (ImageView) findViewById(R.id.image); 
File filePath = getFileStreamPath(fileName);
imageView.setImageDrawable(Drawable.createFromPath(filePath));