安卓:内存错误的使用了位图时 [英] Android: out of memory error when using bitmaps

查看:288
本文介绍了安卓:内存错误的使用了位图时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我经常收到内存不足的错误在我的应用程序。我相信这与我从服务器上下载的位图的事情。任何想法,为什么?

  **在我的活性的方法,设置了ListView的:**私有类NewsFeedArrayAdapter扩展ArrayAdapter< AnimalLocationLog> {    ArrayList的< AnimalLocationLog>物体;
    上下文语境;
    ArrayList的<串GT;网址;
    ImageDownloader下载;    公共NewsFeedArrayAdapter(上下文的背景下,INT textViewResourceId,ArrayList的< AnimalLocationLog>对象的ArrayList<串GT;的网址){
        超(背景下,textViewResourceId,对象);
        this.context =背景;
        this.objects =物体;
        this.urls =网址;
        下载=新ImageDownloader();
    }    @覆盖
    公共查看getView(INT位置,查看convertView,父母的ViewGroup){
        LayoutInflater吹气=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        查看rowView = inflater.inflate(R.layout.list_single,父母,假);        AnimalLocationLog电流= objects.get(位置);        ImageView的图像=(ImageView的)rowView.findViewById(R.id.icon);
        TextView的FIRSTLINE =(TextView中)rowView.findViewById(R.id.firstline);
        TextView的secondline =(TextView中)rowView.findViewById(R.id.secondline);        //下载外部图像
        downloader.download(urls.get(仓位14%),图像);        firstline.setText(current.getSpecies());
        secondline.setText(花斑+ current.getDateTime()的toString(YYYY-MM-DD H:M));        返回rowView;
    }
** ImageDownloader.java:**    公共类ImageDownloader {        地图<弦乐,位图> imageCache;        公共ImageDownloader(){
            imageCache =新的HashMap<弦乐,位图>();        }        //下载功能
        公共无效下载(字符串URL,ImageView的ImageView的){
             如果(cancelPotentialDownload(URL,ImageView的)){                 //缓存code就在这里
                 字符串文件名=将String.valueOf(url.hash code());
                 文件f =新的文件(getCacheDirectory(imageView.getContext()),文件名);                  //是在我们的记忆缓存中的位图?
                 位图位图= NULL;                  位=(位图)imageCache.get(f.getPath());                  如果(位图== NULL){                      位= BitmapFactory.de codeFILE(f.getPath());                      如果(位图!= NULL){
                          imageCache.put(f.getPath(),位图);
                      }                  }
                  //没有?下载它
                  如果(位图== NULL){
                      BitmapDownloaderTask任务=新BitmapDownloaderTask(ImageView的);
                      DownloadedDrawable downloadedDrawable =新DownloadedDrawable(任务);
                      imageView.setImageDrawable(downloadedDrawable);
                      task.execute(URL);
                  }其他{
                      //是?设置图像
                      imageView.setImageBitmap(位图);
                  }
             }
        }        //取消下载(仅供内部使用)
        私有静态布尔cancelPotentialDownload(字符串URL,ImageView的ImageView的){
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(ImageView的);            如果(bitmapDownloaderTask!= NULL){
                字符串bitmapUrl = bitmapDownloaderTask.url;
                如果((bitmapUrl == NULL)||(!bitmapUrl.equals(URL))){
                    bitmapDownloaderTask.cancel(真);
                }其他{
                    //相同的URL已经被下载。
                    返回false;
                }
            }
            返回true;
        }        //如果存在的ImageView的得到现有下载
        私有静态BitmapDownloaderTask getBitmapDownloaderTask(ImageView的ImageView的){
            如果(ImageView的!= NULL){
                可绘制可绘制= imageView.getDrawable();
                如果(绘制的instanceof DownloadedDrawable){
                    DownloadedDrawable downloadedDrawable =(DownloadedDrawable)绘制;
                    返回downloadedDrawable.getBitmapDownloaderTask();
                }
            }
            返回null;
        }        //我们的缓存功能
        //查找目录保存缓存图像
        私有静态文件getCacheDirectory(上下文的背景下){
            串sdState = android.os.Environment.getExternalStorageState();
            文件cacheDir;            如果(sdState.equals(android.os.Environment.MEDIA_MOUNTED)){
                文件sdDir = android.os.Environment.getExternalStorageDirectory();                // TODO:在此处更改diretcory
                cacheDir =新的文件(sdDir,数据/ TAC / imagess);
            }
            其他
                cacheDir = context.getCacheDir();            如果(!cacheDir.exists())
                cacheDir.mkdirs();
                返回cacheDir;
        }        私人无效WriteFile的(BMP位图,文件f){
              FileOutputStream中走出= NULL;              尝试{
                OUT =新的FileOutputStream(F);
                bmp.com preSS(Bitmap.Com pressFormat.PNG,80出);
              }赶上(例外五){
                e.printStackTrace();
              }
              最后{
                尝试{如果out.close()(满分!= NULL); }
                赶上(例外前){}
              }
        }
        ///////////////////////        //下载的AsyncTask
        公共类BitmapDownloaderTask扩展的AsyncTask<弦乐,太虚,位图> {
            私人字符串URL;
            私人最终的WeakReference< ImageView的> imageViewReference;            公共BitmapDownloaderTask(ImageView的ImageView的){
                imageViewReference =新的WeakReference< ImageView的>(ImageView的);
            }            @覆盖
            //实际的下载方法,在任务线程中运行
            保护位图doInBackground(字符串... PARAMS){
                 // PARAMS来自execute()调用:PARAMS [0]是的URL。
                 URL =(字符串)PARAMS [0];
                 返回downloadBitmap(PARAMS [0]);
            }            @覆盖
            //一旦图像被下载,它关联到的ImageView
            保护无效onPostExecute(位图位图){
                如果(isCancelled()){
                    位= NULL;
                }                如果(imageViewReference!= NULL){
                    ImageView的ImageView的= imageViewReference.get();
                    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(ImageView的);
                    //改变位图只有在这个过程中仍与它相关联
                    如果(这种== bitmapDownloaderTask){
                        imageView.setImageBitmap(位图);                        //缓存图片
                        字符串文件名=将String.valueOf(url.hash code());
                        文件f =新的文件(getCacheDirectory(imageView.getContext()),文件名);                        imageCache.put(f.getPath(),位图);                        写文件(位图,F);
                    }
                }
            }
        }        静态类DownloadedDrawable扩展ColorDrawable {
            私人最终的WeakReference< BitmapDownloaderTask> bitmapDownloaderTaskReference;            公共DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask){
                超(Color.BLACK);
                bitmapDownloaderTaskReference =
                    新的WeakReference< BitmapDownloaderTask>(bitmapDownloaderTask);
            }            公共BitmapDownloaderTask getBitmapDownloaderTask(){
                返回bitmapDownloaderTaskReference.get();
            }
        }        //实际的下载code
        静态位图downloadBitmap(字符串URL){
            的HttpParams PARAMS =新BasicHttpParams();
            params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);
            HttpClient的客户端=新DefaultHttpClient(PARAMS);
            最终HTTPGET调用getRequest =新HTTPGET(URL);            尝试{
                HTT presponse响应= client.execute(调用getRequest);
                。最终诠释状态code = response.getStatusLine()的getStatus code();
                如果(状态code!= HttpStatus.SC_OK){
                    Log.w(ImageDownloader,错误+状态code +,同时检索从位图+网址);
                    返回null;
                }                最终HttpEntity实体= response.getEntity();
                如果(实体!= NULL){
                    为InputStream的InputStream = NULL;
                    尝试{
                        的InputStream = entity.getContent();
                        最后的位图位图= BitmapFactory.de codeStream(InputStream的);
                        返回位图;
                    } {最后
                        如果(的InputStream!= NULL){
                            inputStream.close();
                        }
                        entity.consumeContent();
                    }
                }
            }赶上(例外五){
                //可以提供IOException异常或IllegalStateException异常更明确的错误信息
                getRequest.abort();
                ; Log.w(ImageDownloader+ URL + e.toString()错误而来自检索的位图)
            } {最后
                如果(客户端!= NULL){
                    //client.close();
                }
            }
            返回null;
        }
    }


解决方案

如果您有高分辨率的图像,你应该扩展他们失望。参见下加载缩小版本到内存的话题。结果
http://developer.android.com/training/displaying-bitmaps/load -bitmap.html 结果
内存不足错误的Andr​​oid

在如何避免它们:结果
<一href=\"http://stackoverflow.com/questions/19151719/how-to-avoid-out-of-memory-error-while-using-bitmap-in-android\">how以避免内存不足的错误,而在Android的使用位图

对于大略介绍:结果
http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/
http://android-developers.blogspot.de/2009/01 /avoiding-memory-leaks.html

i often get out of memory errors in my app. I believe it has to do with the bitmaps i download from the server. Any ideas why?

**A method in my activity that sets up ListView:**

private class NewsFeedArrayAdapter extends ArrayAdapter<AnimalLocationLog> {

    ArrayList<AnimalLocationLog> objects;
    Context context;
    ArrayList<String> urls;
    ImageDownloader downloader;     

    public NewsFeedArrayAdapter(Context context, int textViewResourceId, ArrayList<AnimalLocationLog> objects, ArrayList<String> urls) {
        super(context, textViewResourceId, objects);
        this.context = context;
        this.objects = objects;
        this.urls = urls;
        downloader = new ImageDownloader();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.list_single, parent, false);

        AnimalLocationLog current = objects.get(position);

        ImageView image = (ImageView) rowView.findViewById(R.id.icon);
        TextView firstline = (TextView) rowView.findViewById(R.id.firstline);
        TextView secondline = (TextView) rowView.findViewById(R.id.secondline);

        // Download external images
        downloader.download(urls.get(position % 14), image);

        firstline.setText(current.getSpecies());
        secondline.setText("Spotted " + current.getDateTime().toString("yyyy-MM-dd H:m"));

        return rowView;
    }


**ImageDownloader.java:**

    public class ImageDownloader {

        Map<String,Bitmap> imageCache;

        public ImageDownloader(){
            imageCache = new HashMap<String, Bitmap>();

        }

        //download function
        public void download(String url, ImageView imageView) {
             if (cancelPotentialDownload(url, imageView)) {

                 //Caching code right here
                 String filename = String.valueOf(url.hashCode());
                 File f = new File(getCacheDirectory(imageView.getContext()), filename);

                  // Is the bitmap in our memory cache?
                 Bitmap bitmap = null;

                  bitmap = (Bitmap)imageCache.get(f.getPath());

                  if(bitmap == null){

                      bitmap = BitmapFactory.decodeFile(f.getPath());

                      if(bitmap != null){
                          imageCache.put(f.getPath(), bitmap);
                      }

                  }
                  //No? download it
                  if(bitmap == null){
                      BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);
                      DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
                      imageView.setImageDrawable(downloadedDrawable);
                      task.execute(url);
                  }else{
                      //Yes? set the image
                      imageView.setImageBitmap(bitmap);
                  }
             }
        }

        //cancel a download (internal only)
        private static boolean cancelPotentialDownload(String url, ImageView imageView) {
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

            if (bitmapDownloaderTask != null) {
                String bitmapUrl = bitmapDownloaderTask.url;
                if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
                    bitmapDownloaderTask.cancel(true);
                } else {
                    // The same URL is already being downloaded.
                    return false;
                }
            }
            return true;
        }

        //gets an existing download if one exists for the imageview
        private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
            if (imageView != null) {
                Drawable drawable = imageView.getDrawable();
                if (drawable instanceof DownloadedDrawable) {
                    DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
                    return downloadedDrawable.getBitmapDownloaderTask();
                }
            }
            return null;
        }

        //our caching functions
        // Find the dir to save cached images
        private static File getCacheDirectory(Context context){
            String sdState = android.os.Environment.getExternalStorageState();
            File cacheDir;

            if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
                File sdDir = android.os.Environment.getExternalStorageDirectory();  

                //TODO : Change your diretcory here
                cacheDir = new File(sdDir,"data/tac/imagess");
            }
            else
                cacheDir = context.getCacheDir();

            if(!cacheDir.exists())
                cacheDir.mkdirs();
                return cacheDir;
        }

        private void writeFile(Bitmap bmp, File f) {
              FileOutputStream out = null;

              try {
                out = new FileOutputStream(f);
                bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
              } catch (Exception e) {
                e.printStackTrace();
              }
              finally { 
                try { if (out != null ) out.close(); }
                catch(Exception ex) {} 
              }
        }
        ///////////////////////

        //download asynctask
        public class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
            private String url;
            private final WeakReference<ImageView> imageViewReference;

            public BitmapDownloaderTask(ImageView imageView) {
                imageViewReference = new WeakReference<ImageView>(imageView);
            }

            @Override
            // Actual download method, run in the task thread
            protected Bitmap doInBackground(String... params) {
                 // params comes from the execute() call: params[0] is the url.
                 url = (String)params[0];
                 return downloadBitmap(params[0]);
            }

            @Override
            // Once the image is downloaded, associates it to the imageView
            protected void onPostExecute(Bitmap bitmap) {
                if (isCancelled()) {
                    bitmap = null;
                }

                if (imageViewReference != null) {
                    ImageView imageView = imageViewReference.get();
                    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
                    // Change bitmap only if this process is still associated with it
                    if (this == bitmapDownloaderTask) {
                        imageView.setImageBitmap(bitmap);

                        //cache the image


                        String filename = String.valueOf(url.hashCode());
                        File f = new File(getCacheDirectory(imageView.getContext()), filename);

                        imageCache.put(f.getPath(), bitmap);

                        writeFile(bitmap, f);
                    }
                }
            }


        }

        static class DownloadedDrawable extends ColorDrawable {
            private final WeakReference<BitmapDownloaderTask> bitmapDownloaderTaskReference;

            public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
                super(Color.BLACK);
                bitmapDownloaderTaskReference =
                    new WeakReference<BitmapDownloaderTask>(bitmapDownloaderTask);
            }

            public BitmapDownloaderTask getBitmapDownloaderTask() {
                return bitmapDownloaderTaskReference.get();
            }
        }

        //the actual download code
        static Bitmap downloadBitmap(String url) {
            HttpParams params = new BasicHttpParams();
            params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
            HttpClient client = new DefaultHttpClient(params);
            final HttpGet getRequest = new HttpGet(url);

            try {
                HttpResponse response = client.execute(getRequest);
                final int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode != HttpStatus.SC_OK) { 
                    Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url); 
                    return null;
                }

                final HttpEntity entity = response.getEntity();
                if (entity != null) {
                    InputStream inputStream = null;
                    try {
                        inputStream = entity.getContent(); 
                        final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                        return bitmap;
                    } finally {
                        if (inputStream != null) {
                            inputStream.close();  
                        }
                        entity.consumeContent();
                    }
                }
            } catch (Exception e) {
                // Could provide a more explicit error message for IOException or IllegalStateException
                getRequest.abort();
                Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString());
            } finally {
                if (client != null) {
                    //client.close();
                }
            }
            return null;
        }
    }

解决方案

If you have high resolution image , you should scale them down. See the topic under Load a Scaled Down Version into Memory.
http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
Out of memory error android

On how to avoid them:
how to avoid out of memory error while using bitmap in android

For an oveview:
http://blogs.innovationm.com/android-out-of-memory-error-causes-solution-and-best-practices/ http://android-developers.blogspot.de/2009/01/avoiding-memory-leaks.html

这篇关于安卓:内存错误的使用了位图时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆