Context详解(API29)


Context是一个抽象类,我们通过这个Context可以访问包内的资源(res和assets)和启动其他组件(activity、service、broadcast)以及系统服务(systemService)等。所以Context提供了一个应用程序运行环境,在Context的环境里,应用才可以访问资源,才能和其他组件、服务交互,Context定义了一套基本功能接口,我们可以理解为一套规范,而Activity和Service是实现这套规范的具体实现类(其实内部是ContextImpl统一实现的)。所以可以这样说,Context是维持Android程序中各个组件能够正常工作的一个核心功能类。

因为出于安全的考虑,Android是不允许Activity或者Dialog凭空出现的,一个Activity的启动必须建立在另一个Activity的基础之上,也就是以此形成了返回栈。而Dialog则必须在一个Activity上面弹出(如果是系统的除外),因此这种情况下我们只能使用Activity类型的Context。但是(targetSdkVersion >= Build.VERSION_CODES.N && targetSdkVersion < Build.VERSION_CODES.P)是允许的,看api28的源码。

//ContextImpl.java
 @Override
    public void startActivity(Intent intent, Bundle options) {
        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in. A bug was existed between N and O-MR1 which allowed this to work. We
        // maintain this for backwards compatibility.
        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;

        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && (targetSdkVersion < Build.VERSION_CODES.N
                        || targetSdkVersion >= Build.VERSION_CODES.P)
                && (options == null
                        || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                            + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                            + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }

Context实例化

  • Context是个抽象类
  • ContextWrapper是Context的包装类,内部持有一个Context的引用mBase(ContextImpl类型对象),所有操作都是通过ContextImpl来实现的
  • ContextThemeWrapper与主题theme有关
  • Application(1个context)、Activity/Service(每个对应一个ContextImpl)
  • ContextImpl实例化都是在各自的attach中,传递过来的
Activity中的ContextImpl实例化
  • Activity启动时,通过classLoader加载activity名字,并实例化activity对象。

  • activity继承自ContextThemeWrapper,ContextThemeWrapper继承自ContextWrapper,ContextWrapper继承自Context。

  • 类加载之前需要先加载其父类,类实例化时会先实例化其父类

  • 实例化activity之后,在activity的attach之前,实例化了一个ContextImpl对象。

  • 在activity的attach()方法中,绑定了其父类contextWrapper的contextImpl对象。

//ActivityThread.java
 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        ComponentName component = r.intent.getComponent();
        ContextImpl appContext = createBaseContextForActivity(r); //创建activity的contextImpl实例
        Activity activity = null;

			// classLoader加载实例化activity
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); 
          
  			// 回调activity的attach
            activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

			 // 回调activity的onCreate
             mInstrumentation.callActivityOnCreate(activity, r.state);
           
        return activity;
    }

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

createBaseContextForActivity®; //创建activity的contextImpl实例对象

//ContextImpl.java
static ContextImpl createActivityContext(ActivityThread mainThread,
            LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
            Configuration overrideConfiguration) {
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
                activityToken, null, 0, classLoader);

		//ResourceManager是个单例对象
        final ResourcesManager resourcesManager = ResourcesManager.getInstance();

        return context;
    }

activity.attach中绑定contextImpl对象

//Activity.java
public class Activity extends ContextThemeWrapper

 final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        //绑定ContextWrapper的实现类contextImpl
        attachBaseContext(context);
        //实例化window对象
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    }

 @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase); //回调ContextThemeWrapper方法
    }

ContextThemeWrapper.java

public class ContextThemeWrapper extends ContextWrapper {

 @Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase); //回调ContextWrpper方法
    }
}

ContextWrpper.java

public class ContextWrapper extends Context {
    Context mBase; //真正实现功能的类

    protected void attachBaseContext(Context base) {
        mBase = base; //每个activity都会绑定一个ContextImpl对象
    }
 }

在这里插入图片描述

Service中的ContextImpl实例化
private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
         	//通过类加载机制实例化service对象
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
       		//创建ContextImpl对象
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService()); //绑定service和contextImpl对象
            service.onCreate();
            mServices.put(data.token, service);
    }

service中创建ContextImpl对象

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        return createAppContext(mainThread, packageInfo, null);
    }

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
            String opPackageName) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null, opPackageName);
        context.setResources(packageInfo.getResources());
        return context;
    }
Application中的ContextImpl实例化
  • activityThread.main() ->attach(false) ->ams.attachApplication(mAppThread, startSeq)
  • 在ams中回调mAppThread.bindApplication()
  • mAppThread是ApplicationThread对象,回调其中的bindApplication()
  • sendMessage(H.BIND_APPLICATION, data),给H发送消息
  • 回到主线程,在H(handler)中处理消息,handleBindApplication(data)
  • AppBindData.info.makeApplication()创建application对象并绑定ContextImpl(info是LoadedApk对象)
//LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

	        //通过类加载方式实例化application,并绑定ContextImpl
            java.lang.ClassLoader cl = getClassLoader();
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext); 
            appContext.setOuterContext(app);
       
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
		
		//回调callApplicationOnCreate方法
    	instrumentation.callApplicationOnCreate(app); 
        return app;
    }

参考:
Android插件化基础2----理解Context

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值