原文地址:http://topic.csdn.net/u/20110215/21/12f944f5-83e3-4f98-aff7-5e0a1212d8ab.html
其中比较有用的理解:
一个APK进程只有一个Context: 这个Context就是ApplicationContext,从Context继承过来。
ApplicationContext可以看做是针对整个系统的全局处理接口,因为:
它负责和系统服务打交道
RPC通信由他通过那些XXXServiceManager和XXXService来处理。
其他一些模块,比如Activity,Service等,也是从Context继承而来的。
比如Acitivity在attach到主线程(ActivityThread)时,会用ApplicationContext来初始化这个Activity,这样就OK了。
比如Activity中StartService,调用过程如下:
Activity.StartService
(Activity继承自ContextWraper,实际会执行 ContextWraper中的)
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
这里面的mBase实际就是ApplicationContext
ApplicationContext中的实现如下:
@Override
public ComponentName startService(Intent service) {
try {
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
if (cn != null && cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
}
return cn;
} catch (RemoteException e) {
return null;
}
}
通过系统服务来做的。
总之:context就是将这些系统服务提供的功能,完美的包装起来了,其中的RPC过程,用户无需关心。好像
这些功能就是在那,自己可以随便使用(要知道跨进程通信和调用,是非常难和麻烦的事情)。
在android中context可以作很多操作,但是最主要的功能是加载和访问资源。在android中有两种context,一种是 application context,一种是activity context,通常我们在各种类和方法间传递的是activity context。
比如一个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,保存状态信息,再创建一个新的。
比如我们写了一个应用程序,它需要加载一个很大的图片,我们不希望每次旋转屏 幕的时候都销毁这个图片,重新加载。实现这个要求的简单想法就是定义一个静态的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.getApplication方法获取。
避免context相关的内存泄露,记住以下几点:
1. 不要让生命周期长的对象引用activity context,即保证引用activity的对象要与activity本身生命周期是一样的
2. 对于生命周期长的对象,可以使用application context
3. 避免非静态的内部类,尽量使用静态类,避免生命周期问题,注意内部类对外部对象引用导致的生命周期变化
分享到:
相关推荐
Application Context是整个应用程序级别的上下文,它不会随着Activity的创建和销毁而改变。因此,我们可以利用Application Context来实现全局的数据共享。首先,我们需要创建一个自定义的Application类,继承自`...
Context主要分为三类:Application Context、Activity Context和Service Context。它们各有不同的用途: 1. Application Context:它代表整个应用程序的生命周期,不依赖于任何Activity或Service。通常用于那些在...
其实我们应用启动的时候会启动Application这个类,这个类是在AndroidManifest.xml文件里其实是默认的 <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity ...
Activity、Service和Application都是Context的子类,因此它们都可以被视为一种Context。Activity通常代表用户界面,Service则用于后台运行,而Application则是整个应用的全局对象,它在应用生命周期开始时创建,并且...
首先,我们要明白Context的三种主要类型:Application、Activity和Service。它们都是Context的子类,但各自的角色不同: 1. **Application**:全局的应用上下文,生命周期贯穿整个应用程序,一般用于存储全局变量和...
1. **避免内存泄漏**:长时间持有Activity的Context会导致内存泄漏,应优先考虑使用Application Context,除非必须使用Activity的Context。 2. **生命周期管理**:了解不同类型的Context与组件的生命周期关系,避免...
通常,我们可以在Activity、Service或Application中直接获取`Context`实例。然而,在非UI线程或自定义类中,可能无法直接获得`Context`,这时候反射就派上用场了。 要通过反射获取`Context`实例,首先我们需要一个...
通常,Application、Activity或Service类会持有Context。假设我们有一个名为`MyApplication`的自定义Application类,我们可以获取该类的Class对象。 ```java Class<?> contextHolderClass = Class.forName(...
Activity 继承自 Context,同时 Activity 还实现了其他的接口,我们可以这样看,Activity 在语法上 extends 了 Context,其本质上是一个 Context,但同时它实现了许多接口,扩充了 Context 的功能,扩充之后的类成为...
在Android应用开发中,Fragment和Activity是两个非常重要的组件,它们负责展示用户界面并处理用户交互。有时,我们可能需要在Fragment和Activity之间进行复杂的通信,例如传递数据或执行异步任务。在这种情况下,...
在Android中,最常见的`Context`类型有`Application`、`Activity`和`Service`。它们各自有不同的生命周期和作用范围,选择合适的`Context`类型对于避免内存泄漏和保持应用稳定性至关重要。 在`Activity`中,`...
Context主要分为三类:Application、Activity和Service,它们都继承自Context。Activity直接继承自ContextThemeWrapper,涉及到用户界面的展示,包含了主题相关的接口,而Application和Service则直接继承自...
1. 获取应用上下文(Application Context):通常,我们可以在Application或者Activity的子类中保存一个静态的ApplicationContext实例。例如: ```java public class MyApplication extends Application { private...
今天在研究context的时候,对application和activity context有了一定的了解,下面是从网上复制过来的资料 Application context和Activity context的区别: 这是两种不同的context,也是最常见的两种。第一种中...
需要注意的是,不同类型的`Context`有不同的生命周期和范围,例如`Activity`的`Context`随着活动的生命周期变化,而`Application`的`Context`则在整个应用程序生命周期内保持不变。 总的来说,`Context`在Android...
`ApplicationDemo` 通常是一个示例项目,用于展示如何在Android应用中有效地使用 `Application` 类以及 `Context` 相关的知识。 `Context` 在Android中扮演着多种角色,主要包括以下几个方面: 1. **资源访问**:`...
比如,Activity的Context与应用程序的生命周期紧密相关,而Application的Context则贯穿整个应用程序的生命周期。 总结一下,本教程“012_android 之消息提示toast 和Context”将详细介绍如何在Android应用中使用...
常见的Context类型有Application Context和Activity Context,它们的区别在于作用范围和生命周期。Application Context在整个应用生命周期内存在,而Activity Context随着Activity的创建和销毁而变化。 接下来,...
3. **使用Application或BaseActivity**:如果你的应用只有一个主Activity或者所有Activity都继承自同一个BaseActivity,可以在BaseActivity的onResume()方法中记录当前Activity,这样就可以随时知道栈顶的Activity是...
但注意,由于Activity是Android系统的组件,创建实例时需要Context,因此通常需要在Application或Service中进行。 3. 注册Activity:在Android系统中,所有的Activity都需要在AndroidManifest.xml中声明。为了动态...