到底是群居好,还是自己一个人独立好,不分情况,考虑所有的情况
什么是Context
大家在开发App时,肯定很多时候都用到了这个东西,获取资源啊,启动activity啊,等等,但是这到底是什么?
Context
看源码:
/**
* Interface to global information about an application environment. This is
* an abstract class whose implementation is provided by
* the Android system. It
* allows access to application-specific resources and classes, as well as
* up-calls for application-level operations such as launching activities,
* broadcasting and receiving intents, etc.
*/
public abstract class Context {
...
//获得系统级服务
public abstract Object getSystemService(String name);
//通过一个Intent启动Activity
public abstract void startActivity(Intent intent);
//启动Service
public abstract ComponentName startService(Intent service);
//根据文件名得到SharedPreferences对象
public abstract SharedPreferences getSharedPreferences(String name,int mode);
...
}
翻译一下上面的注释:
应用程序环境的全局信息的接口。 它是一个抽象类,它的执行被Android系统所提供。它允许获取以应用为特征的资源和类型,是一个统领一些资源(应用程序环境变量等)的上下文。
其他不看,总结Context
应用程序环境的全局信息,就像单词翻译过来的—–上下文
是个抽象类,不管,会有实现的
通过它我们可以获取应用程序的资源和类(包括应用级别操作,如启动Activity,发广播,接受Intent等)
一个应用的Context个数
APP Context总数 = Application数(1) + Activity数(Customer) + Service数(Customer);
为什么是这样?继承不一样,下面讲。
开始分析:
ContextImpl
实现了Context类的所有API。
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context {
//所有Application程序公用一个mPackageInfo对象
/*package*/
ActivityThread.PackageInfo mPackageInfo;
private Context mOuterContext;
......
}
ContextWrapper
ContextImpl的代理,该类的构造函数包含了一个真正的Context(ContextImpl对象)引用,ContextImpl的装饰者模式
/**
* Proxying implementation of Context that simply delegates all of its calls to
* another Context. Can be subclassed to modify behavior without changing
* the original Context.
*/
public class ContextWrapper extends Context {
//该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
* 创建Application、Service、Activity,会调用该方法给mBase属性赋值
*/
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
......
}
ContextThemeWrapper
该类内部包含了主题Theme相关的接口,即android:theme属性指定的。
/**
* A ContextWrapper that allows you to modify the theme from what is in the
* wrapped context.
*/
public class ContextThemeWrapper extends ContextWrapper {
//该属性指向一个ContextIml实例,一般在创建Application、Service、Activity时赋值
private Context mBase;
//mBase赋值方式同样有一下两种
public ContextThemeWrapper(Context base, int themeres) {
super(base);
mBase = base;
mThemeResource = themeres;
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
mBase = newBase;
}
}
再来看看Activity、Service、Application类的继承关系源码:
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback {
......
}
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
......
}
public class Application extends ContextWrapper implements ComponentCallbacks2 {
......
}
枯燥的来了
Activity中ContextImpl实例化
归纳一下:
通过startActivity启动一个新的Activity—>回调ActivityThread的
handleLaunchActivity()
方法—>内部会调用performLaunchActivity()
方法
performLaunchActivity()
方法—>调用createBaseContextForActivity(xx,xx)
方法
createBaseContextForActivity(xx,xx )
中创建了ContextImpl对象,并且调用了contextImpl的setOuterContext(activity)
,将当前的Activity对象赋值给了内部成员变量mOuterContext,所以到了这一步,ContextImpl类关联了Activity最后通过调用
Activity.attach( xx,xx,·····)
方法,将createBaseContextForActivity
返回的ContextImpl对象传入到ContextWrapper类的mBase变量,这样,ContextWrapper类的成员mBase就被实例化l
Service中ContextImpl实例化
图不贴了,和Activity差不多
通过startService启动一个新的Activity—>回调ActivityThread的
handleCreateService()
方法创建了ContextImpl对象,并赋值mOuterContext,产生关联。调用
Service.attach
方法,将ContextImpl对象传入到ContextWrapper类的mBase变量
Application中ContextImpl实例化
一个APP以后每次重新启动时都会首先创建Application对象(每个APP都有一个唯一的全局Application对象,与整个APP的生命周期相同)
创建Application—>回调ActivityThread的
handleBindApplication()
方法调用该方法中的LoadedApk类的
makeApplication
方法创建ContextImpl对象,,并赋值mOuterContext,产生关联。中间还有一系列的attach传递
最后调用Application类的attach方法,ContextImpl对象传入到ContextWrapper类的mBase变量
真复杂,再精简
不管创建Activity,还是Service,还是Application
在ActivityThread线程回调中创建ContextImpl对象,并把自身赋值给内部的mOuterContext对象,产生关联
最后经过里面一系列的方法传递,调用相应的attach,将ContextImpl对象传入到ContextWrapper类的mBase变量。