android内存溢出等各种常见问题
来源:互联网 发布:中国农业银行程序员岗 编辑:程序博客网 时间:2024/04/30 02:19
最近开发了一款和LBS相结合的android软件。项目虽小,但在开发过程中遇到的问题却是不少。今天写此博文,一为总结,再次理一下在解决问题时的思考过程;二为分享,希望遇到同样问题的童鞋们有一个参考;三为交流学习,虽然有些解决方法没有bug,但性能上本人还不甚满意,如果您有更好的解决办法或发现任何问题,欢迎批评指正,多多交流学习。
下面列举出我所遇到的问题及解决方法(注:所有测试都是基于android 4.0.4系统)。
1).百度地图刷新得不到及时响应,出现灰色区域
解决方法:在manifest文件中的application标签下添加 android:hardwareAccelerated="false",但添加之后还是不行。最后在 非主activity(主activity:启动软件显示的第一个activity)中添加 android:hardwareAccelerated="true",启用硬件加速,然后地图响应就很流畅了。
2).用腾讯微博开放平台发表带图片的微博时抛NetWorkOnMainThreadException
解决方法:在onCreate方法中添加如下代码就OK了:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());在2.3以前的系统中不会出现此问题。或者通过异步方式进行此操作,因为它说的是**OnMainThread**,那么不在主线程中进行这种耗时的网络操作,就不会有问题了。
3).Context的使用问题
大家都知道,context容易引发内存溢出,而且很隐蔽,所以大多数情况都尽量使用Application context,因为这种context和Application有相同的生命周期,不会引起内存泄露。但当我要显示一个AlertDialog时,使用Application context就会抛出异常:android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application,必须使用Activity context。查看google提供的文档,Activity->ContextThemeWrapper->ContextWrapper->Context;Application->ContextWrapper->Context,可以看出Context是Activity和Application的父类,通过Activity和Application都可以获得Context对象。但问题就是,显示dialog相当于显示一个自定义窗口,Application context是无法获得Window对象的,而Activity可以通过getWindow()方法获得Window对象。为了防止context引发的内存溢出,请记住以下3点:
- 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
- 对于生命周期长的对象,可以使用application context
- 避免非静态的内部类,尽量使用静态内部类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
这是我遇到的最头疼的一个问题,在网上也查了很多资料,大多数都一样。如弱引用(WeakReference),软引用(SoftReference)等,这些在一定程度上的确可以优化,但并不能彻底解决问题,图片很多的时候,还是会出现内存溢出。最主要的还是要及时回收bitmap,这个及时,,如何及时?在网上看到一些方法:
//前面还有部分代码未贴出 originalImage = BitmapFactory.decodeFile(path, options); width = originalImage.getWidth(); height = originalImage.getHeight(); Bitmap bitmapWithReflection = Bitmap.createBitmap(dw, dh, Config.ARGB_8888); Canvas canvas = new Canvas(bitmapWithReflection); canvas.drawBitmap(originalImage, 0, 0, null); ImageView imageView = new ImageView(mContext); imageView.setImageBitmap(originalImage); imageView.setLayoutParams(new GalleryFlow.LayoutParams(width, height)); mImages[index++]=imageView; bitmapWithReflection.recycle(); bitmapWithReflection = null; System.gc();这样如果马上回收originalImage,图片就无法显示;显示后再回收?由于每初始化一张图片,originalImage对象就会指向另一块内存,而指向原来的bitmap内存的对象则被覆盖了,当我们要回收该bitmap时,却发现找不到指向该内存的对象,自然也就无法回收了。
我的解决方法是:延迟加载图片,每初始化一张图片,就把bitmap对象存储在一个Bitmap数组中,ImageView再从该数组中取得对应的bitmap。需要回收的时候,可以通过数组中bitmap对象来释放所占用的内存。不管有多少图片,都可以保证在内存中的图片数量不超过M张(M可由自己控制,如8张。通过option参数可以控制加载到内存的图片的大小,一般800*600*4=1920000byte=1.8M,8张一般不会超出android单个程序内存限制)。部分代码如下:
public View getView(int position, View convertView, ViewGroup parent) {if(convertView==null){if(mImages[position]==null && bitmaps[position]==null){int high = position+mem_size;/** * 当图片的索引位置大于或等于mem_size时,要考虑回收两头的bitmap内存; * 否则只需考虑回收后面的内存。 */if(position>=mem_size){int low=position-mem_size;if(bitmaps[low]!=null){this.destory(low);}if(high<size && bitmaps[high]!=null){this.destory(high);}}else{if(high<size && bitmaps[high]!=null){this.destory(high);}}System.gc();try {ImageView imageView = new ImageView(mContext);bitmaps[position]=this.createView(paths.get(position));imageView.setImageBitmap(bitmaps[position]);imageView.setLayoutParams(new GalleryFlow.LayoutParams(width, height));mImages[position]=imageView;} catch (Exception e) {e.printStackTrace();}finally{convertView=mImages[position];}}else{convertView=mImages[position];}}return convertView;} private void destory(int index){ bitmaps[index].recycle(); bitmaps[index]=null; mImages[index]=null; }
算是解决了bitmap内存溢出问题,但是性能上还有待优化。
- android内存溢出等各种常见问题
- Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
- Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
- Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
- Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
- Java常见问题分析(内存溢出、内存泄露、线程阻塞等)
- jvm内存溢出的各种
- Java内存溢出和连接池死锁等各种混乱问题的解决
- atoi实现,考虑溢出等各种情况
- android内存溢出问题
- android bitmap内存溢出
- android 内存溢出优化
- Android内存溢出
- Android内存溢出
- android内存溢出
- Android内存溢出
- Android内存溢出(OOM)
- Android检测内存溢出
- 【Oracle入门系列】第01章_数据库基础
- 1.frontpage+access数据库打开
- javascript解析json串
- 变法先驱及封建制度的奠基人
- 多事件监听--java
- android内存溢出等各种常见问题
- 检测按键
- JNI接口函数<一>
- 公务员考试
- [9]技术浅谈——偶遇佛者
- 【Oracle入门系列】第02章_Oracle入门
- Cocos2d-x 10的CCUserDefault不能在android下保存内容
- JNI接口函数<二>
- 《一元二次方程求解窗口——Java第十三周》