Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1272530
  • 博文数量: 247
  • 博客积分: 5587
  • 博客等级: 大校
  • 技术积分: 2060
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-24 13:27
文章分类
文章存档

2012年(101)

2011年(44)

2010年(102)

分类: 嵌入式

2012-10-15 19:52:59

我发现开发Android应用时最普遍的错误是 “java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget”。当Activity使用大量的位图(Bitmap),屏幕方向改变后就会频繁出现这个错误。因为Activity被销毁,然后重新创建, 布局从XML文件加载,这个过程消耗了虚拟机为Bitmap分配的可用内存。
由于位图对Activity有交叉引用,在先前的Activity布局中,位图没有被垃圾回收器适当释放。经过诸多经验,我发现一个好的方法可以解决此问题。

首先,在你的XML布局的父视图设置id属性:

  1. <span style="font-size:16px;">xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android=""  
  3.  android:layout_width="fill_parent"  
  4.  android:layout_height="fill_parent"  
  5.  android:id="@+id/RootView"  
  6. >  
  7. ...span>  

然后,在你的Activity的onDestroy()方法中,调用unbindDrawable()方法并传递一个父视图引用,之后调用System.gc()方法。
  1. "font-size:16px;">@Override  
  2. protected void onDestroy() {  
  3.     super.onDestroy();  
  4.    
  5.     unbindDrawables(findViewById(R.id.RootView));  
  6.     System.gc();  
  7. }  
  8.    
  9. private void unbindDrawables(View view) {  
  10.     if (view.getBackground() != null) {  
  11.         view.getBackground().setCallback(null);  
  12.     }  
  13.     if (view instanceof ViewGroup) {  
  14.         for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {  
  15.             unbindDrawables(((ViewGroup) view).getChildAt(i));  
  16.         }  
  17.         ((ViewGroup) view).removeAllViews();  
  18.     }  
  19. }  

unbindDrawable()方法会递归浏览视图树,并且:
•在所有背景图片中移除回调接口
•在每个ViewGroup中移除对应的子视图
这解决了我们的Mobialia应用中许多问题。
2011-03-30更新:
今天来自partanBits的@luiskap告诉我另一个好方法。如果你不需要不同的布局去适应横竖屏,你可以让你的Activity在屏幕方向改变 时作出相应的反应:在Manifest文件中添加 android:configChanges="keyboardHidden|orientation",重写 onConfigurationChanged方法,调用setContentView重用已经创建的视图。有一个很好例子。
阅读(4330) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~