Context(三) -- Service创建Context

313 阅读2分钟

「这是我参与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中创建以上单例的话