Context可能是Android应用程序中最重要的元素,也可能最容易被滥用
Context 对象是很常见的,并且使用非常频繁,它能很容易的造成这样的局面。加载资源,显示一个新Activity,获得一个系统服务,获得内部文件路径,创建视图都需要一个
Context 来完成这些任务,我想做的是提供一些见解来讲解使用Context的一些技巧,让你更有效的利用在你的应用程序中。
Context 类型
并非所有Context对象生来平等,根据Android应用程序组件,你访问Context稍有不同:
Application - 是你应用程序运行过程中的一个单例,它可以通过 getApplication() 从Activity或者Service中获得,
getApplicationContext() 可以从所有继承Context的对象中获得。不管在哪个方法获得,你都是得到的一个相同的实例。
Activity/Service - 继承
ContextWrapper实现其相同的API,但是代理中的所有方法调用了一个隐藏的内部Context对象,也被称为base context。每当framework创建一个新Activity或者Service实例时,
它也创建一个新ContextImpl的实例来将
组件
包裹
。每个Activity或Service,对于
base contex
,是唯一的实例。
BroadcastReceiver -
本身不是一个Context对象,但是framework通过context对象在onReceive()中,每次new broadcast会被传进来。这个实例是一个
ReceiverRestrictedContext 有两个主要的功能被禁用 调用
registerReceiver() 和 bindService(),这两个函数不允许出现在BroadcastReceiver.onReceive()内。每次一个接收的广播进行处理,传递给它的
Context 是一个新实例。
ContentProvider - 也没有Context对象,
而是给出一个创建时通过的getContext()可以访问。如果ContentProvider的运行本地主叫方(即相同的应用程序),那么这将实际上返回相同的应用程序的单身。但是,如果两者是在单独的进程,这将是一个新创建的实例,表示包提供程序正在运行。
保存参考
第一个问题 我们需要保存一个Context对象或者类的一个生命周期中你需要保存。例如,创建一个自定义的单体,需要一个Context对象来加载资源或者访问一个
ContentProvider,
当前的活动或服务
在这个单体保存参考。
坏的单体:
public class CustomManager {
private static CustomManager sInstance;
public static CustomManager getInstance(Context context) {
if (sInstance == null) {
sInstance = new CustomManager(context);
}
return sInstance;
}
private Context mContext;
private CustomManager(Context context) {
mContext = context;
}
}
这个问题是,我们不知道Context来自哪儿,它不是一个安全的持有对象的引用,如果它结束了一个Activity或Service,这是一个问题,因为一个单身的管理由一个单一的封闭类内的静态引用。这意味着,我们的对象,它引用的所有其它对象,将永远不会被垃圾收集。如果这方面的活动,我们将有效地保持人质在内存中所有的意见和与它相关的其他潜在的大对象;创建泄漏。
为了防止这一点,我们修改的单身始终引用
Application Context :
好的单体:
public class CustomManager {
private static CustomManager sInstance;
public static CustomManager getInstance(Context context) {
if (sInstance == null) {
//Always pass in the Application Context
sInstance = new CustomManager(
context.getApplicationContext());
}
return sInstance;
}
private Context mContext;
private CustomManager(Context context) {
mContext = context;
}
}
现在,context来自哪儿并不重要了,我们持有的对象是安全的,application context 是单例的,所以我们不会
那么,为什么我们不能永远只是引用应用程序上下文?并且永远不必担心有关创建泄漏?答案,因为我躲避在引进,是因为一个上下文是不等于另一个。