android图片加载oom
Ⅰ android bitmap内存溢出的完美解决方案,Gallery加载大量图片的时候,总是会oom,大侠们帮忙啊,谢谢啦
用弱引用,目前是解决此问题最好方式 WeakReference, 然后用完及时的赋成null
Ⅱ android 为什么容易出现oom
头些年的设备内存容量小,dalvik虚拟机被设置为16M内存运行,为了保留足够的内存,对于bitmap限制为一半,即8M,8M是个什么概念呢,如果RAGB8888格式的图片,8M就是800万像素的图片,一般的手机都可以达到甚至超过这个标准。所以通常出现OOM都是在以前的设备上运行解码图片的时候产生的。
比较新的版本SDK支持配置largeheap选项,会得到一个较大的运行内存,再加上这两年设备的内存容量大大增加,几乎可以与PC相当,这个问题就没那么容易出现了。
Ⅲ android编程读取文件有oom错误
Out Of Memory 就是内存爆了,你加载的文件太大了 ,所以导致溢出了。如果你加载图片,你可以搜一下解决图片OOM的方法,网络上有很多,还有demo。
Ⅳ android 异步下载图片到listview中,报oom异常
对啊,listview需要重绘的,
你就把图片保存起来就好了啊
然后用callback加载
先判断是否下载了,下载过了就直接设置,没下载过再去加载
Ⅳ Android 图片OOM
你从sd 卡中读取图片,要将原图进行缩放显示,手机内内存有限,有的图片资源较大,正如你说的,还是反复读取,一张图片就能把它搞死
Ⅵ 如何解决上传多张图片时遇到的oom问题
一、OOM问题出现的场景和原因
一个好的app总少不了精美的图片,所以Android开发中图片的加载总是避免不了的,而在加载图片过程中,如果处理不当则会出现OOM的问题。那么如何彻底解决这个问题呢?本文将具体介绍这方面的知识。
首先我们来总结一下,在加载图片过程中出现的OOM的场景无非就这么几种:
1、 加载的图片过大
2、 一次加载的图片过多
3、 以上两种情况兼有
那么为什么在以上场景下会出现OOM问题呢?实际上在API文档中有着明确的说明,出现OMM的主要原因有两点:
1、移动设备会限制每个app所能够使用的内存,最小为16M,有的设备分配的会更多,如24、32M、64M等等不一,总之会有限制,不会让你无限制的使用。
2、在andorid中图片加载到内存中是以位图的方式存储的,在android2.3之后默认情况下使用ARGB_8888,这种方式下每个像素要使用4各字节来存储。所以加载图片是会占用大量的内存。
场景和原因我们都分析完了,下面我们来看看如何解决这些问题。
二、解决大图加载问题
首先先来解决大图加载的问题,一般在实际应用中展示图片时,因屏幕尺寸及布局显示的原因,我们没有必要加载原始大图,只需要按照比例采样缩放即可。这样即节省内存又能保证图片不失真,具体实施步骤如下:
1、在不加载图片内容的基础上,去解码图片得到图片的尺寸信息
这里需要用的BitmapFactory的decode系列方法和BitmapFactory.Options。当使用decode系列方法加载图片时,一定要将Options的inJustDecodeBounds属性设置为true。
BitmapFactory.Options ptions = new BitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeFile(path, options);2、根据获取的图片的尺寸和要展示在界面的尺寸计算缩放比例。public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height reqHeight || width reqWidth) { if (width height) { inSampleSize = Math.round((float) height / (float) reqHeight); } else { inSampleSize = Math.round((float) width / (float) reqWidth); } } return inSampleSize; }3、根据计算的比例缩放图片。//计算图片的缩放比例 options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); options.inJustDecodeBounds = false; Bitmap bitmap= BitmapFactory.decodeFile(path, options);
根据缩放比例,会比原始大图节省很多内存,效果图如下:
三、批量加载大图
下面我们看看如何批量加载大图,首先第一步还是我们上面所讲到的,要根据界面展示图片控件的大小来确定图片的缩放比例。在此我们使用gridview加载本地图片为例,具体步骤如下:
1、通过系统提供的contentprovider加载外部存储器中的所有图片地址private void loadPhotoPaths(){ Cursor cursor= getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, null); while(cursor.moveToNext()){ String path = cursor.getString(cursor.getColumnIndex(MediaColumns.DATA)); paths.add(path); } cursor.close(); }2、自定义adapter,在adapter的getview方法中加载图片@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder=null; if(convertView==null){ convertView = LayoutInflater.from(this.mContext).inflate(R.layout.grid_item_layout, null); holder = new ViewHolder(); holder.photo=(ImageView)convertView.findViewById(R.id.photo); convertView.setTag(holder); }else{ holder=(ViewHolder)convertView.getTag(); } final String path = this.paths.get(position); holder.photo.setImageBitmap(imageLoader.getBitmapFromCache(path)); return convertView; }
通过以上关键两个步骤后,我们发现程序运行后,用户体验特别差,半天没有反应,很明显这是因为我们在主线程中加载大量的图片,这是不合适的。在这里我们要将图片的加载工作放到子线程中进行,改造自定义的ImageLoader工具类,为其添加一个线程池对象,用来管理用于下载图片的子线程。
private ExecutorService executor; private ImageLoader(Context mContxt) { super(); executor = Executors.newFixedThreadPool(3); } //加载图片的异步方法,含有回调监听 public void loadImage(final ImageView view, final String path, final int reqWidth, final int reqHeight, final onBitmapLoadedListener callback){ final Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 1: Bitmap bitmap = (Bitmap)msg.obj; callback.displayImage(view, bitmap); break; default: break; } } }; executor.execute(new Runnable() { @Override public void run() { Bitmap bitmap = loadBitmapInBackground(path, reqWidth, reqHeight); putBitmapInMemey(path, bitmap); Message msg = mHandler.obtainMessage(1); msg.obj = bitmap; mHandler.sendMessage(msg); } }); }
通过改造后用户体验明显好多了,效果图如下:
虽然效果有所提升,但是在加载过程中还存在两个比较严重的问题:
1、 图片错位显示
2、 当我们滑动速度过快的时候,图片加载速度过慢
经过分析原因不难找出,主要是因为我们时候holder缓存了grid的item进行重用和线程池中的加载任务过多所造成的,只需要对程序稍作修改,具体如下:
Adapter中:
holder.photo.setImageResource(R.drawable.ic_launcher); holder.photo.setTag(path); imageLoader.loadImage(holder.photo, path, DensityUtil.dip2px(80), DensityUtil.dip2px(80), new onBitmapLoadedListener() { @Override public void displayImage(ImageView view, Bitmap bitmap) { String imagePath= view.getTag().toString(); if(imagePath.equals(path)){ view.setImageBitmap(bitmap); } } });
ImageLoader中:
executor.execute(new Runnable() { @Override public void run() { String key = view.getTag().toString(); if (key.equals(path)) { Bitmap bitmap = loadBitmapInBackground(path, reqWidth, reqHeight); putBitmapInMemey(path, bitmap); Message msg = mHandler.obtainMessage(1); msg.obj = bitmap; mHandler.sendMessage(msg); } } });
为了获得更好的用户体验,我们还可以继续优化,即对图片进行缓存,缓存我们可以分为两个部分内存缓存磁盘缓存,本文例子加载的是本地图片所有只进行了内存缓存。对ImageLoader对象继续修改,添加LruCache对象用于缓存图片。
private ImageLoader(Context mContxt) { super(); executor = Executors.newFixedThreadPool(3); //将应用的八分之一作为图片缓存 ActivityManager am=(ActivityManager)mContxt.getSystemService(Context.ACTIVITY_SERVICE); int maxSize = am.getMemoryClass()*1024*1024/8; mCache = new LruCachestring, bitmap=""(maxSize){ @Override protected int sizeOf(String key, Bitmap value) { return value.getRowBytes()*value.getHeight(); } }; } //存图片到缓存 public void putBitmapInMemey(String path,Bitmap bitmap){ if(path==null) return; if(bitmap==null) return; if(getBitmapFromCache(path)==null){ this.mCache.put(path, bitmap); } } public Bitmap getBitmapFromCache(String path){ return mCache.get(path); }/string,
在loadImage方法中异步加载图片前先从内存中取,具体代码请下载案例。
四、总结
总结一下解决加载图片出现OOM的问题主要有以下方法:
1、 不要加载原始大图,根据显示控件进行比例缩放后加载其缩略图。
2、 不要在主线程中加载图片,主要在listview和gridview中使用异步加载图片是要注意处理图片错位和无用线程的问题。
3、 使用缓存,根据实际情况确定是否使用双缓存和缓存大小。
小伙伴们看懂了嘛?想要自己测试的,可以点击下载工程运行测试哦!
Ⅶ android oom是怎么引起的
OOM产生可能的原因是因为 1、加载大图片导致内存溢出 2、大量内存泄露
Ⅷ Android 开发中怎样加载图像才能避免OOM
进行缓存,好多第三方封装好的加载图片的框架,UniversalImageLoader、Picasso、Fresco、Glide等等都是github上面开源的。
贴出链接自己去下载:https://github.com/nostra13/Android-Universal-Image-Loader
https://github.com/square/picasso
https://github.com/bumptech/glide
Ⅸ android如何加载超大分辨率图片
因为你要求图片不能缩放,不能降低质量,而且有7M,oom是必须的,所以你能做的只能是加载你看得见的地方,意思就是说剪裁着看,先不加载,按屏幕的分辨率的1.5倍或多一些进行剪裁(这个度自己控件),当向某一个方向滑时,检测坐标如果快超出时,加载右边的下一幅。
这个有点类似于游戏中的地图贴图,也是分块的。
Ⅹ oom 是什么意思
OOM Killer(Out of Memory Killer) 是当系统内存严重不足时 linux 内核采用的杀掉进程,释放内存的机制。
OOM Killer 通过检查所有正在运行的进程,然后根据自己的算法给每个进程一个 badness 分数,拥有最高 badness 分数的进程将会在内存不足时被杀掉。
它打分的算法如下:
某一个进程和它所有的子进程都占用了很多内存的将会打一个高分。
为了释放足够的内存来解决这种情况,将杀死最少数量的进程(最好是一个进程)。
内核进程和其他较重要的进程会被打成相对较低的分。
上面打分的标准意味着,当 OOM killer 选择杀死的进程时,将选择一个使用大量内存,有很多子进程且不是系统进程的进程。
简单来讲,oom-killer 的原则就是损失最小、收益最大,因此它会让杀死的进程数尽可能小、释放的内存尽可能大。在数据库服务器上,Mysql 被分配的内存一般不会小,因此容易成为 oom-killer 选择的对象。
“既然发生了 OOM,那必然是内存不足,内存不足这个问题产生原因很多。
首先第一个就是 MySQL 自身内存的规划有问题,这就涉及到 mysql 相应的配置参数。
另一个可以想到的原因就是一般部署 MySQL 的服务器,都会部署很多的监控和定时任务脚本,而这些脚本往往缺少必要的内存限制,导致在高峰期的时候占用大量的内存,导致触发 Linux 的 oom-killer 机制,最终 MySQL 无辜躺枪牺牲。”