Android开发之—内存泄露篇

本文深入探讨了Android应用开发中内存泄露的问题及其原因,着重解释了上下文对象context在内存泄露中的角色,并提供了避免内存泄露的有效方法。通过实例分析,展示了如何正确使用Application上下文对象来减少内存泄露风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android开发之—内存泄露篇
 
众所周知,手机开发,内存相当宝贵。至少在当前的T-Moble G1上,手机只有16M的内存可用,与PC应用开发的内存,真是天壤之别啊。因此如何规避手机应用开发内存泄漏问题,是手机应用开发的重中之重。
  
在开发过程当中,大部分内存泄漏的原因是,持有上下文引用的长周期对象,要知道,java的GC机制,只对无引用的对象才采取回收措施的。
  
在Andorid中,上下文对象context被用来做很多操作,但绝大多数是用来加载和访问资源文件。这就是为什么每个部件的构造函数都持有这个上下文对象作为入参。
  
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
   
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
   
  setContentView(label);
}
  
这段代码意味着,TextView持有Activity的引用,那么它也将持有所以Activity持有对象的引用,通常是整个视图层级和所有的资源。因此如果你一直保持着与Activity的引用,那么GC将不会进行回收,最终导致内存泄漏。如果你不小心,在开发当中很容易出现这种情况。
  
在手机屏幕旋转时,系统默认销毁当前的Activity并创建一个新的Activity。这样做的结果是,Android将重新加载系统资UI源文件。假设你写的一个程序,有一个较大的bitmap,你不希望每次屏幕旋转时都加载这个图片,那么你将定义成static变量,如:
  
private static Drawable sBackground; 
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
   
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
   
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
   
  setContentView(label);
}
这段代码虽然快,但是错误的,容易导致内存溢出。为什么呢?
在屏幕一次旋转时,第一个Activity注定将泄漏,因为Drawable附属在一个TextView对象上,View被设定为drawable上的一个回调。因此,drawable持有TextView的引用,而TextView持有Activity的引用,这样导致轮流关联引用到任何对象。
  
改进方法:在Activity的onDestory方法中,setCallBack为null
@Override
    protected void onDestroy() {
    super.onDestroy(); 
    unbindDrawables(findViewById(R.id.RootView));
    System.gc();
    }
  
    private void unbindDrawables(View view) {
        if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
        ((ViewGroup) view).removeAllViews();
        }
    }
  
  
总结:避免内存泄漏的两大方针。
1、  避免引用当前上下文作用域之外的对象,就像以上例子的static对象在onCreate方法被引用一样。同样,内部类被外部类引用也存在同样的危险;
  
2、  使用Application上下文对象。这个对象长期存在,而不依赖于Activity的生命周期。如果你打算保留一个需要上下文Context对象的长期对象,那么建议你使用Application对象,获取Application对象的方法, Context.getApplicationContext()  或者Activity.getApplication().
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值