Android系统源码分析--Context

Android是一个开源系统,至少说是大部分开源的,源代码的学习对于咱们学习Android帮助很是大,可能不少人看看源码时感受代码太多了,不知道从何开始,今天我就从基本的部分开始跟你们一块儿学习Android源码。
声明:本篇以及之后Android源码分析是基于Android-7.1.2_r11(7.1最终版代码)源码进行分析。若是以后切换会进行声明。但愿对照源码学习的要找对应版本进行查看。java

在开始介绍Context前咱们先看一张Android系统框架层的图:android

从上面图能够看到Android系统主要分为五层:应用层,应用框架层,Native库和运行环境,硬件抽象层和Linux内核层。本章不重点讲Android系统框架,只是开始给你们展现一下,有个了解,咱们先从Framework层开始学习,首先学习Context,下面进入正题。数据库

概述:

作Android开发的朋友在开发过程当中时刻用到Context,那么Context究竟是什么,究竟是作什么的咱们详细分析一下。源码中解释Context是一个面向应用全局信息的接口,那么我看看哪些信息与Context有关:微信

  • 获取AssetManager:getAssets();
  • 获取Resources:getResources();
  • 获取PackageManager:getPackageManager();
  • 获取ContentResolver:getContentResolver();
  • 获取主线程Looper:getMainLooper();
  • 获取Application的Context:getApplicationContext();
  • 获取资源文件:getText,getString,getColor,getDrawable,getColorStateList;
  • 设置主题,获取主题资源id:setTheme,getThemeResId;
  • 获取样式属性TypedArray:obtainStyledAttributes();
  • 获取类加载器ClassLoader:getClassLoader();
  • 获取应用信息对象ApplicationInfo:getApplicationInfo();
  • 获取SharedPreferences:getSharedPreferences();
  • 打开文件FileInputStream:openFileInput();
  • 删除文件:deleteFile();
  • 获取文件File:getFileStreamPath();
  • 打开或者建立数据库:openOrCreateDatabase();
  • 移除或者删除数据库:moveDatabaseFrom(),deleteDatabase();
  • 启动Activity:startActivity(),startActivityAsUser(),startActivityForResult(),startActivities();
  • 注册、发送、注销广播:registerReceiver(),sendBroadcast(),sendOrderedBroadcast(),unregisterReceiver();
  • 启动、绑定、解除绑定、中止服务:startService(),bindService(),unbindService(),stopService();
  • 获取系统服务:getSystemService();
  • 检查权限(Android 6.0以上):checkPermission();
  • 根据应用名建立Context:createPackageContext();
  • 根据应用信息建立Context:createApplicationContext();
  • 获取显示信息对象Display:getDisplay();

主要的信息关联就是这些,还有一些不经常使用的或者废弃的没有再展现,有兴趣本身看看源码,官方解释很清晰。上面有个获取系统服务,咱们下面把全部的系统服务列举一下(前面是服务,后面是获取服务的名称):网络

  • android.view.WindowManager--#WINDOW_SERVICE-----------------------------窗口管理
  • android.view.LayoutInflater--#LAYOUT_INFLATER_SERVICE-------------------布局加载器
  • android.app.ActivityManager--#ACTIVITY_SERVICE--------------------------Activity管理器
  • android.os.PowerManager--#POWER_SERVICE---------------------------------电源管理
  • android.app.AlarmManager--#ALARM_SERVICE--------------------------------提醒管理
  • android.app.NotificationManager--#NOTIFICATION_SERVICE------------------通知管理
  • android.app.KeyguardManager--#KEYGUARD_SERVICE--------------------------键盘管理
  • android.location.LocationManager--#LOCATION_SERVICE---------------------定位管理
  • android.app.SearchManager--#SEARCH_SERVICE------------------------------搜索管理
  • android.hardware.SensorManager--#SENSOR_SERVICE-------------------------传感器管理
  • android.os.storage.StorageManager--#STORAGE_SERVICE---------------------存储管理
  • android.os.Vibrator--#VIBRATOR_SERVICE----------------------------------震动管理
  • android.net.ConnectivityManager--#CONNECTIVITY_SERVICE------------------网络管理
  • android.net.wifi.WifiManager--#WIFI_SERVICE-----------------------------Wifi管理
  • android.media.AudioManager--#AUDIO_SERVICE------------------------------音频管理
  • android.media.MediaRouter--#MEDIA_ROUTER_SERVICE------------------------媒体路由器
  • android.telephony.TelephonyManager--#TELEPHONY_SERVICE------------------电话管理
  • android.telephony.SubscriptionManager--#TELEPHONY_SUBSCRIPTION_SERVICE--双卡信息管理
  • android.telephony.CarrierConfigManager--#CARRIER_CONFIG_SERVICE---------电话配置信息管理
  • android.view.inputmethod.InputMethodManager--#INPUT_METHOD_SERVICE------输入法管理
  • android.app.UiModeManager--#UI_MODE_SERVICE-----------------------------UI模式管理
  • android.app.DownloadManager--#DOWNLOAD_SERVICE--------------------------下载管理
  • android.os.BatteryManager--#BATTERY_SERVICE-----------------------------电池管理
  • android.app.job.JobScheduler--#JOB_SCHEDULER_SERVICE--------------------任务执行者
  • android.app.usage.NetworkStatsManager--#NETWORK_STATS_SERVICE-----------网络状态管理
  • android.os.HardwarePropertiesManager--#HARDWARE_PROPERTIES_SERVICE------硬件属性管理

上面这些服务,你能够经过Context.getSystemService(Context.名称)直接获取,而后进行操做。app

类图

首先看一下类图关系:框架

讲解:

1.ContextImpl、ContextWrapper与Context的关系ide

Context是一个静态类,ContextImpl和ContextWrapper都继承了Context,也就是都实现了Context的静态方法,可是,从代码中咱们看到ContextImpl是Context静态方法的详细实现类,而ContextWrapper是调用了mBase对应的方法,而mBase是Context,从代码跟踪看mBase其实就是ContextImpl,所以ContextWrapper最终是调用ContextImpl中的实现方法。也就是说咱们调用的Context中的任何方法都是在ContextImpl中处理的,所以咱们在跟踪代码时只须要去ContextImpl中查看对应方法处理就行了。上面只是介绍,下面咱们根据具体代码来分析一下到底怎么实现的。函数

从ContextWrapper代码中咱们能够看到(不贴所有代码了),只有构造函数、attachBaseContext方法以及getBaseContext方法不是复写方法,其余方方法均为复写方法:oop

【ContextWrapper.java】

Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }

    /** * Set the base context for this ContextWrapper. All calls will then be * delegated to the base context. Throws * IllegalStateException if a base context has already been set. * * @param base The new base context for this wrapper. */
    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    /** * @return the base context as set by the constructor or setBaseContext */
    public Context getBaseContext() {
        return mBase;
    }复制代码

咱们能够看到只有构造函数和attachBaseContext方法传入了mBase,那么从attachBaseContext方法中咱们看到若是mBase存在又调用了该方法就会抛出异常,所以咱们知道若是调用了该方法,那么构造函数不能传入这个值,咱们看一下哪些地方调用了这个attachBaseContext方法,由代码能够看到Application、activity和service均调用了这个方法,首先咱们来看Application中的代码:

【Application.java】

/** * @hide */
    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }复制代码

Application中的attach方法中调用了attachBaseContext方法,参数context也是经过attach方法传入的,那么咱们再跟踪这个attach方法:

是在Instrumentation类中调用的:

【Instrumentation.java】

static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }复制代码

上面方法调用地方是:

【Instrumentation.java】

public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return newApplication(cl.loadClass(className), context);
    }复制代码

从代码能够看到是在new Application时调用的,那么咱们接着看哪里调用了这个方法:

【LoadedApk.java】

public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
        ...

        try {
            ...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ...
        }
        ...
        return app;
    }复制代码

上面方法是在LoadedApk类中调用的,咱们先不分析这个类,后续咱们会详细讲这个过程,咱们先分析上面这段代码,咱们看到这里面经过调用ContextImpl.createAppContext方法来建立ContextImpl,而后将参数传入newApplication方法,所以咱们看到上面的mBase就是ContextImpl,那么还有Activity和Service.咱们先分析Service,由于从关系图能够看到Service和Application都是直接继承ContextWrapper,而Activity则是继承ContextThemeWrapper,ContextThemeWrapper继承ContextWrapper。

【Service.java】

public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) {
        attachBaseContext(context);
        ...
    }复制代码

attachBaseContext方法是在Service中的attach方法中调用的,接着看attach方法的调用:

【ActivityThread.java】

private void handleCreateService(CreateServiceData data) {
        ...
            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,
                    ActivityManagerNative.getDefault());
            service.onCreate();
         ...
    }复制代码

在这里咱们看到传入的context就是ContextImpl,从而获得验证,下面咱们还看到service.onCreate方法,咱们看到了先调用attach方法而后调用onCreate方法。

最后咱们看一下Activity,从上面关系图咱们看到,Activity不是直接继承ContextWrapper,而是继承的ContextThemeWrapper,ContextThemeWrapper继承ContextWrapper。从名字咱们能够看到ContextThemeWrapper包含主题的信息,其实不难理解,四大组件只有Activity是带界面的,其余都是没有界面的,所以Activity须要主题信息来显示不一样的界面效果。在ContextThemeWrapper中咱们看到复写了attachBaseContext方法,方法中只有一行代码就是调用父类的attachBaseContext方法。以下所示:

【ContextThemeWrapper.java】

@Override
    protected void attachBaseContext(Context newBase) {
        super.attachBaseContext(newBase);
    }复制代码

在Activity中只有一个方法中调用了该方法,看代码:

【Activity.java】

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) {
        attachBaseContext(context);

        ...
    }复制代码

咱们接着追踪attach方法,看代码:

【ActivitThread.java】

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
       ...

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                ...
                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);

                ...
            }
            ...
        return activity;
    }复制代码

方法performLaunchActivity实际上是启动Activity的方法,这里咱们暂时不讲,后续咱们会详细讲解,咱们先理清楚Context,从上面代码咱们能够看到此处传入的Context是经过createBaseContextForActivity方法建立的,那么咱们看一下这个方法:

【ActivitThread.java】

private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        ...

        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.token, displayId, r.overrideConfig);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        ...
        return baseContext;
    }复制代码

从上面代码我肯能够清楚的看到baseContext是appContext赋值的,而appContext就是ContextImpl,所以Activity中的Context也是ContextImpl。到如今咱们已经搞清楚了ContextImpl、Context、ContextWrapper、ContextThemeWrapper以及Application、Service和Activity的关系,那么之后看源码咱们就知道与Context相关的实现方法都在ContextImpl类中,若是须要看详细实现过程只须要去ContextImpl类中找到相应方法开始跟踪便可。

从下一章咱们开始讲解四大组件的启动过程。

同步发布:www.codemx.cn/2017/06/05/…

Android开发群:192508518

微信公众帐号:Code-MX

注:本文原创,转载请注明出处,多谢。

相关文章
相关标签/搜索