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

在开始介绍Context前我们先看一张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.名称)直接获取,然后进行操作。

类图

首先看一下类图关系:

讲解:

1.ContextImpl、ContextWrapper与Context的关系

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

从ContextWrapper代码中我们可以看到(不贴全部代码了),只有构造函数、attachBaseContext方法以及getBaseContext方法不是复写方法,其他方方法均为复写方法:

【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】

    @Overrideprotected 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

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

Android系统源码分析--Context相关推荐

  1. (连载)Android系统源码分析--Android系统启动流程之Linux内核

    > **这是一个连载的博文系列,我将持续为大家提供尽可能透彻的Android源码分析 [github连载地址](https://github.com/foxleezh/AOSP/issues/3 ...

  2. android 系统源码分析

    获得Android源码后,我们来分析源码结构.源码的全部工程分为如下三个部分. ①Core Project:核心工程部分,这是建立Android系统的基础,保存在根目录的各个文件夹中. ②Extern ...

  3. Android系统源码分析--Activity的finish过程

    上一篇我们分析了Activity的启动流程,由于代码量很大,还是没有分析的很详细,但是基本流程都出来了,更详细的东西还是要去看源码.这一章来分析Activity的finish过程,分析一下finish ...

  4. Android系统源码分析/多媒体框架/音频子系统/常用结构体分析-audio.h

    audio_stream_type_t 定义音频流类型,主要是手机系统各类典型的音频流做出属性上的区分,举个例子:电话和媒体2种类型的音频不管从输出的设备(耳机.功放.还是蓝牙)都是存在明显的不同.把 ...

  5. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  6. 【Android SDM660源码分析】- 02 - UEFI XBL QcomChargerApp充电流程代码分析

    [Android SDM660源码分析]- 02 - UEFI XBL QcomChargerApp充电流程代码分析 一.加载 UEFI 默认应用程序 1.1 LaunchDefaultBDSApps ...

  7. 【Android SDM660源码分析】- 03 - UEFI XBL GraphicsOutput BMP图片显示流程

    [Android SDM660源码分析]- 03 - UEFI XBL GraphicsOutput BMP图片显示流程 1. GraphicsOutput.h 2. 显示驱动初化 DisplayDx ...

  8. Android系统源码目录及功能介绍

    Android的移植按如下流程:     1.android linux 内核的普通驱动移植,让内核可以在目标平台上运行起来.     2.正确挂载文件系统,确保内核启动参数和 android 源代码 ...

  9. android系统源码之 系统应用安装过程(下)

    android系统源码之 系统应用安装过程(上) :http://blog.csdn.net/king1425/article/details/70135813 下图是PackageParser主要数 ...

  10. Android框架源码分析——从设计模式角度看 Retrofit 核心源码

    Android框架源码分析--从设计模式角度看 Retrofit 核心源码 Retrofit中用到了许多常见的设计模式:代理模式.外观模式.构建者模式等.我们将从这三种设计模式入手,分析 Retrof ...

最新文章

  1. Nexus Repository Manager 3.0 发布
  2. git:Git fetch和git pull的区别, 解决Git报错:error: You have not concluded your merge (MERGE_HEAD exists)....
  3. cookie中文乱码
  4. 电子科大计算机大类包括专业,电子科技大学a类学科有哪些?附电子科大a类学科名单...
  5. [网络安全自学篇] 八十.WHUCTF之WEB类解题思路WP(代码审计、文件包含、过滤绕过、SQL注入)
  6. MongoDB学习笔记(一)环境搭建与常用操作
  7. 真格量化-隐含波动率购买
  8. 晚间看图片就高亮,这体验太差
  9. 劝你别把开源的数据分析项目写在简历上了!!!
  10. 滴滴入局同城货运,一场闪电战,还是持久战?
  11. 恐惧迷宫小游戏抖音快手超火
  12. react-子传父案例(汇率转换)
  13. 登录实例失败,原因: 连接实例 i-wz972sda3z2cf3u3t9a1 (47.112.162.228:3389) 超时: 10 秒,请检查网络是否可达或者白名单设置
  14. 2021上海建筑施工八大员之安全员模拟题集及答案解析
  15. 计算属性普通函数写法 和 set get 写法
  16. [模版]尽整些歪门邪道
  17. c语言编译星座测试,用c语言编写程序,判断输入的日期(月,日)属于哪个星座?...
  18. X站全称是什么_工作中学习-没有校惯导之前为什么PFD不显示飞机姿态,而IFSD却能显示...
  19. macOS Big Sur系统安装盘小白制作教程
  20. 云服务器环境安装、卸载与配置:mysql

热门文章

  1. Atitit.HTTP 代理原理及实现 正向代理与反向代理attilax总结
  2. paip.中文 分词 ---paoding 3.1 的使用
  3. Julia: wsl ubuntu下安装、vscode及配置profile错误补正
  4. 我们眼中的资管管理行业三要素
  5. 中基协会长洪磊:尽快制定大类资产配置管理办法 推非保本理财转型
  6. (转)“版本上线延时”问题与对策的探讨
  7. Julia : 数组(矩阵)的条件过滤
  8. 官宣!什么是新基建时代的混合云? | 凌云时刻
  9. 【优化算法】大鼠群优化器算法(RSO)【含Matlab源码 1837期】
  10. 【答题卡识别】基于matlab形态学答题卡识别【含Matlab源码 1135期】