美文网首页
Andriod中Context的理解

Andriod中Context的理解

作者: feifei_fly | 来源:发表于2020-12-11 20:11 被阅读0次

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

  • Context是什么?承担哪些责任
  • 常用的Context类,以及继承关系
  • 一个App中会有多少个ContextImpl实例

一、Context继承关系

Android中Context的继承关系如下:


image
  • Activity,Service,Application都是ContextWrapper的子类
  • ContextWrapper里面引用着一个ContextImpl实例;
  • ContextWrapper里所有的方法都是通过调用ContextImpl进行实现;

二、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);
            }
        }
    }
  • (1)通过LoadedApk 和ActivityThread 创建一个ContextImpl 实例
  • (2)为ContextImpl设置OuterContext
  • (3) attach()方法 中,将ContextImpl实例传递给Service的mBase属性上。

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);
}
  • (1)创建ContextImpl
  • (2)利用Instrumentation创建Activity
  • (3)完成Activity和ContextImpl的双向绑定

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

相关文章

  • Andriod中Context的理解

    本文主要回答以下几个问题: Context是什么?承担哪些责任 常用的Context类,以及继承关系 一个App中...

  • React中的Context理解

    今天看了下react官网的context,记录下学习过程和自己对context的理解。下面从为什么要用和怎么用两个...

  • React-深入探究Context(1)

    前言 React组件中的Context与Android中的Context类似,都可以理解为上下文。而React中的...

  • spring-context理解

    一、context 是什么 我们经常在编程中见到 context 这个单词,当然每个人有每个人的理解,它被理解为:...

  • 对于web中Context的理解

    在 java 中, 常见的 Context 有很多, 例如: ServletContext, ActionCon...

  • 源码学习->05Context

    参考文章 : 1. 理解Android Context理解Application创建过程 Context : 1、...

  • context的理解

    转载自:http://blog.csdn.net/singwhatiwanna/article/details/2...

  • context 的理解

    怎样理解 context 可以理解为场景,也就是用户与操作系统操作的过程,比如你打电话,场景包括电话程序对应的界面...

  • Context理解

    官方文档 https://doc.react-china.org/docs/context.html#api 个人...

  • 理解Context

    此文为Android内核剖析学习 Context是啥 一个Context意味着一个场景,一个场景就是用户和操作系统...

网友评论

      本文标题:Andriod中Context的理解

      本文链接:https://www.haomeiwen.com/subject/sfrsgktx.html