Andriod中Context的理解

2020-12-11  本文已影响0人  feifei_fly

本文主要回答以下几个问题:

一、Context继承关系

Android中Context的继承关系如下:


image

二、Context类

public abstract class Context{
    
}

Context 代表一个上下文信息,是一个抽象类,定义了多个abstract方法,由子类实现具体功能。
如:

1、持有SharePreferences
2、持有DataBaseDir、CahceDir、FileDir 等内部路径
3、持有Resources资源类,进而持有getAssets() 等。
4、持有LoadedApk
5、提供 startActivity()
6、发送 sendBroadcast()
7、支持 startService()

Context持有资源信息,持有loadedApk,具有操作SharePrefrences、操作数据库、启动activity、启动service、发送广播等功能。

对,没错, startActivity()、startService()、startBoradCast()都是Context的行为。

二、ContextImpl 类

ContextImpl是Context的主要实现类,Context所定义众多行为,都是由ContextImpl来完成的。

class ContextImpl extends Context {

 final void setOuterContext(Context context) {
        mOuterContext = context;
    }
    
     @Override
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }
     @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
       @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}

三、ContextWrapper 是Context的包装类。

ContextWrapper 是Context的子类,内部持有一个ContextImpl对象(mBase)。ContextWrapper中所有功能都是由ContextIml实例来完成的。

public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
    
    
      protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }
    
     @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }
    
    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }
    
     @Override
    public void sendBroadcast(Intent intent) {
        mBase.sendBroadcast(intent);
    }
}

ContextWrapper.attachBaseContext()方法将ContextImpl对象的绑定:

ContextWrapper.java
protected void attachBaseContext(Context base) {
      mBase = base;
}

ContextWrapper.mBase指向持有的ContextImpl类,
同时ContextImpl.mOuterContext 指向外部的ContextWrapper类。

ContextImpl.java
final void setOuterContext(Context context) {
      mOuterContext = context;
}

四、Application、Activity、Service 都是ContextWrapper的子类,继承了Context的能力。

4.1、Application的创建:

 private void handleBindApplication(AppBindData data) {
        //这是LoadedApk首次创建的地方
        //创建或加载LoadedApk (一个packageName包名对应一个LoadedApk,
        首次调用创建LoadedApk,然后缓存在mPackages中,再次调用直接取缓存的loadedApk对象。所以LoadedApk 整个进程只有一个实例。
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
        //LoadedApk创建Application对象
         app = data.info.makeApplication(data.restrictedBackupMode, null);

         //调用Application的onCreate()生命周期 
        mInstrumentation.callApplicationOnCreate(app);

    }

LoadedApk中 首先创建了一个ContextImpl实例,利用Instrumentation创建Application实例,然后将application赋值到contextImpl的OuterContext上。至此完成了ContextImpl->ContextWrapper的绑定。

LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
                
                //(1)创建一个ContextImpl实例
              ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
               //(2) 创建一个Application实例
                  app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
                //(3)为contextImpl指令outerContext
        appContext.setOuterContext(app);
            
}

我们再看Instrumentation中,创建Application之后,调用了app.attach(context)方法.

Instrumentation.java
   public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }

Application.attach()方法 调用自身的attachBaseContext(),将ContextImpl实例赋值到ContextWrapper.mBase属性上。至此完成了ContextWrapper->ContextImpl的绑定

Application.java
 /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

4.2、Service的创建

private void handleCreateService(CreateServiceData data) {
  
      
          //获取LoadedApk
          LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
              java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);


            //(1)通过LoadedApk 和ActivityThread 创建一个ContextImpl 实例
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            
            
            //(2)为ContextImpl设置OuterContext
            context.setOuterContext(service);

            //LoadedApk 创建Application对象
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            //(3) attach()方法 中,将ContextImpl实例传递给Service的mBase属性上。
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

4.3、Activity 的创建

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)
 
    //(1)创建ContextImpl
   ContextImpl appContext = createBaseContextForActivity(r);
   //(2)创建Activity
   activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
   //(3)完成Activity和ContextImpl的双向绑定                 
   appContext.setOuterContext(activity);
   activity.attach(appContext, this, getInstrumentation(),...);
}

 private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
   ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
}

4.4、app中ContextImpl实例的个数:

由上面分析可知:

每创建一个Application、Service 或者Activity 就会创建一个ConetxtImpl实例

Appliation和Service中的ContextImpl实例是相同的(创建方式相同,不是同一个实例),而Activity的ContextImpl不同于Application和Service

Applicaiton和Service ContentImpl的创建方式

 ContextImpl context = ContextImpl.createAppContext(this, packageInfo);

Activity中ContextImp的创建方式

 private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
   ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);

五、参考文章

https://www.jianshu.com/p/e65cfcbdd11e

上一篇下一篇

猜你喜欢

热点阅读