「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」
Service的Context创建流程需要从ActivityThread.handleCreateService开始,我们先看看handleCreateService()的代码
- (1) 首先创建一个Service对象
- (2) 再创建一个ContextImpl对象
- (3) 将service对象赋值给ContextImpl中的mOuterContext, 这样一来ContextImpl就可以访问service中的变量和方法了
- (4) 调用service.attach()方法,将创建的context传递给service
- (5) 调用service.onCreate()
private void handleCreateService(CreateServiceData data) {
...
try {
...
// (1)
service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);
} catch (Exception e) {
...
}
try {
// (2)
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
// (3)
context.setOuterContext(service);
...
// (4)
service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
// (5)
service.onCreate();
mServices.put(data.token, service);
}
}
我们再来看看attach()
- attach()方法比较简单,就是将Service类型的ContextImpl赋值给了ContextWrapper中的mBase。我们调用ContextWrapper中的方法实际就是调用ContextImpl中的方法
public final void attach(...) {
attachBaseContext(context);
}
protected void attachBaseContext(Context base) {
mBase = base;
}
Service创建Context就结束了,下面我们一起学习一下Context的几个问题
-
getApplicationContext() 和 getApplication()有区别吗?
getApplicationContext() 和 getApplication() 都是通过 makeApplication() 方法返回的同一个对象。getApplicationContext()是在Context 定义的,所以说只要继承Context的子类都可以调用getApplicationContext()方法。 而 getApplication() 在Context并没有定义,只是在Activity和Service中定义了getApplication()方法,并在创建ActivityThread 的 performLaunchActivity方法中执行 makeApplication()方法创建Application然后使用activity.attach(app)进行的赋值的
-
Context 引起的内存泄露(单例模式导致内存泄漏)
我们向某个单例对象传入Context(某个实例对象),Context来自 Activity或Service(某个具有生命周期的对象),单例对象是由对应类内部的静态引用管理的,即使Activity结束了,单例对象还是存在,这将使得该对象继续持有Context 的引用,造成内存泄漏问题。所以在创建该单例的时候使Application中创建单例的话是没有问题。因为Application的Context生命周期是整个应用,和单例的生命周期一样,因此不会导致内存泄漏。但是,如果你是在Activity中创建以上单例的话