android基础教程之context使用详解

在android中有两种context,一种是application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。

区别联系:

复制代码 代码如下:
public class MyActivity extends Activity {
    public void method() {
       mContext = this;    // since Activity extends Context
       mContext = getApplicationContext();
       mContext = getBaseContext();
    }
 }

this 是Activity 的实例,扩展了Context,其生命周期是Activity 创建到销毁
getApplicationContext() 返回应用的上下文,生命周期是整个应用,应用摧毁它才摧毁
Activity.this的context 返回当前activity的上下文,属于activity ,activity 摧毁他就摧毁
getBaseContext() 返回由构造函数指定或setBaseContext()设置的上下文,SDK文档很少,不推荐使用
搞清楚了生命周期就会在使用过程中犯错误,比如有一个全局的数据操作类用到了context,这个时候就要用到getApplicationContext 而不是用ACtivity,这就保证了数据库的操作与activity无关(不会一直引用Activity的资源,防止内存泄漏)

应用场景:
比如一个activity的onCreate:

复制代码 代码如下:
protected void onCreate(Bundle state) {       
     super.onCreate(state);       
     TextView label = new TextView(this); //传递context给view control       
     label.setText("Leaks are bad");       
     setContentView(label);
}

把activity context传递给view,意味着view拥有一个指向activity的引用,进而引用activity占有的资源:view hierachy, resource等。
这样如果context发生内存泄露的话,就会泄露很多内存。这里泄露的意思是gc没有办法回收activity的内存。

Leaking an entire activity是很容易的一件事。当屏幕旋转的时候,系统会销毁当前的activity,保存状态信息,再创建一个新的activity。
比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏幕的时候都销毁这个图片重新加载。
实现这个要求的简单想法就是定义一个静态的Drawable,这样Activity 类创建销毁它始终保存在内存中。
实现示例:

复制代码 代码如下:
public class myactivity extends Activity {       
       private static Drawable sBackground;       
       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);//drawable attached to a view       
              setContentView(label);       
       }
}

这段程序看起来很简单,但是却问题很大。当屏幕旋转的时候会有leak(即gc没法销毁activity)。
我们刚才说过,屏幕旋转的时候系统会销毁当前的activity。但是当drawable和view关联后,drawable保存了view的reference,即sBackground保存了label的引用,而label保存了activity的引用。
既然drawable不能销毁,它所引用和间接引用的都不能销毁,这样系统就没有办法销毁当前的activity,于是造成了内存泄露。gc对这种类型的内存泄露是无能为力的。

避免这种内存泄露的方法是避免activity中的任何对象的生命周期长过activity,避免由于对象对activity的引用导致activity不能正常被销毁。
我们可以使用application context。
application context伴随application的一生,与activity的生命周期无关。
application context可以通过Context.getApplicationContext()或者Activity.getApplicationContext()方法获取。

避免context相关的内存泄露,记住以下几点:
1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
2. 对于生命周期长的对象,可以使用application context
3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化

时间: 2024-09-27 01:46:59

android基础教程之context使用详解的相关文章

android基础教程之context使用详解_Android

在android中有两种context,一种是application context,一种是activity context,通常我们在各种类和方法间传递的是activity context. 区别联系: 复制代码 代码如下: public class MyActivity extends Activity {    public void method() {       mContext = this;    // since Activity extends Context       m

Android基础知识之broadcast广播详解_Android

Android中的广播用的太多了,今天稍微总结一下. 按注册方式分为两种: 1.静态注册广播: 静态注册广播就是在androidManifest.xml文件中注册广播,假设我们要实现这样一个效果,在一个activity上点击按钮,发送一条广播,这条广播弹出一个toast,显示"静态"二字. 先看看广播接受者: public class MyBroadcast extends BroadcastReceiver { @Override public void onReceive(Cont

Zend Framework教程之Autoloading用法详解_php实例

本文实例讲述了Zend Framework教程之Autoloading用法.分享给大家供大家参考,具体如下: 一.概述 自动加载是一种机制,无需依赖手动编写PHP代码.参考»PHP手册自动加载,一旦自动加载器被定义,你试图使用一个没有定义的类或接口的情况下,它会自动被调用. 使用自动加载,在项目中你不必担心类的存放位置.定义一个良好定义的自动加载器,您不需要考虑一个类文件相对于当前类文件的位置,您只需使用类,自动加载器将自动查找文件. 此外,自动加载,确保只加载一次,提升了性能 -所以可以用它替

AngularJS入门教程之ng-checked 指令详解_AngularJS

AngularJS ng-checked 指令 AngularJS 实例 选择一个或选择所有选项: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script> </head>

Zend Framework教程之Zend_Db_Table用法详解_php实例

本文实例讲述了Zend_Db_Table用法.分享给大家供大家参考,具体如下: 1. 简介 Zend_Db_Table 是Zend Framework的表模块.它通过zend_db_adapter连接到 数据库,为数据库模式检查表对象,并对该表进行操作和查询. 2. 开始 首先需要为抽象类zend_db_table(ares注:该类为抽象类,所以不能直接实例 化,只能先继承该类,然后实例化子类)设定一个默认对数据库adapter;除非你 指定其他类型数据库adapter,否则,所有的zend_d

Android基础知识之broadcast广播详解

Android中的广播用的太多了,今天稍微总结一下. 按注册方式分为两种: 1.静态注册广播: 静态注册广播就是在androidManifest.xml文件中注册广播,假设我们要实现这样一个效果,在一个activity上点击按钮,发送一条广播,这条广播弹出一个toast,显示"静态"二字. 先看看广播接受者: public class MyBroadcast extends BroadcastReceiver { @Override public void onReceive(Cont

android基础教程之android的listview与edittext冲突解决方法

最近遇到一个关于android软键盘的问题.在ListView中每个Item中都有个EditText,在最后的几个Item中,EditText第一次点击界面还能向上弹出,正常显示, 但第二次点击时,软件盘就把最后的几个Item给正当住了.这样很影响用户体验的. 其实解决的办法只要想一下,我相信有经验的开发人员就能够想到,让软键盘在消失的时候让相应Item中的EditText消失焦点clearFouce():但是有个关键的问题, 就是在获得返回事件的时候,如果获得的事件不对那就不会达到想要的效果.

【android基础】之ImageView xml详解

ImageView        1. 类概述 显示任意图像,例如图标. ImageView 类可以加载各种来源的图片(如资源或图片库),需要计算图像的尺寸,比便它可以在其他布局中使用,并提供例如缩放和着色(渲染)各种显示选项. 2.XML属性   属性名称 描述 android:adjustViewBounds 是否保持宽高比.需要与 maxWidth. MaxHeight一起使用,否则单独使用没有效果. android:cropToPadding 是否截取指定区域用空白代替.单独设置无效果,

AngularJS教程之MVC体系结构详解_AngularJS

模型 - 视图 - 控制器或MVC,MVC是普遍的叫法,是一种软件设计模式,用于开发Web应用程序.模型- 视图 - 控制器模式是由以下三部分组成: 模型/Model - 一个负责维护数据模式的最低水平. 视图/View - 负责显示所有或数据到用户的部分. 控制器/Controller - 软件代码控制Model和View之间的相互作用. MVC是受欢迎的,因为它隔离了应用逻辑从用户界面层和支持的关注点分离.这里的控制器接收用于该应用程序的所有请求,制备视图所需要的任何数据.视图,使用制备的控