本人只是Android小菜一个,写技术文章只是为了总结自己最近学习到的知识,从来不敢为人师,如果里面有不正确的地方请大家尽情指出,谢谢!
本文基于原生 Android 9.0 源码来解析 Context.getSystemService 原理:
frameworks/base/core/java/android/app/Activity.java
frameworks/base/core/java/android/view/ContextThemeWrapper.java
frameworks/base/core/java/android/view/LayoutInflater.java
frameworks/base/core/java/android/content/Context.java
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/SystemServiceRegistry.java
复制代码
1. 概述
Android
系统为程序开发者提供了各种各样的系统服务,以满足在不同场景下的需求,例如:
LayoutInflater
:把layout
布局文件渲染成view
控件对象;DownloadManager
:发起下载任务,从特定文件来源中下载文件;CameraManager
:调用系统摄像组件进行拍照录像等功能。
这里只列举了几个常用的系统服务,实际上现在Android
框架中存在的系统服务要远远多于这些,基本涵盖了所有的系统服务类型,同时Android
框架为了帮助程序开发者更便捷地获取和使用这些服务,提供了一个统一的接口Context.getSystemService()
,通过这个接口,开发者可以很方便快捷地获取想要的系统服务。
通过获取LayoutInflater
系统服务实例的过程来简单了解下getSystemService()
的基本使用方法,示例代码如下:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 通过 getSystemService 系统接口获取 LayoutInflater 服务实例
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 2. 使用获取到的 LayoutInflater 服务来把布局文件渲染成控件对象
View view = inflater.inflate(R.layout.view_merge, null);
}
}
复制代码
简直太简单了! 只通过一行代码就获取到了LayoutInflater
实例,然后就可以“肆意”使用这个服务来完成自己想要的功能了。
知道这些就够了吗?当然不是,作为一个“有理想有抱负”的程序员,在知道一项技术的基本用法之后,接下来要做的就是了解其背后的原理和实现方式,争取做到“知其然更知其所以然”。
本文将通过分析系统服务类LayoutInflater
实例的具体获取过程来讲解Context.getSystemService()
的实现原理,虽然其本身的逻辑并不复杂,仍希望能对感兴趣但没有时间查看源码的同学有所帮助。
2. 理解 Context.getSystemService 原理
Android
系统框架中提供的系统服务多种多样,要学习和理解其实现原理,必须要以一个具体的系统服务为切入点,在这里选择LayoutInflater
服务为入口,通过对其实例获取过程的逐步分析来揭开Context.getSystemService()
的神秘面纱。
2.1 LayoutInflater 获取过程
前面已经给出获取LayoutInflater
服务实例的示例代码,如下:
// 在 Activity 中调用 getSystemService 获取 LayoutInflater 服务对象。
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
复制代码
这里通过Activity.getSystemService()
获取LayoutInflater
服务实例,直接看这块代码:
public Object getSystemService(@ServiceName @NonNull String name) {
// 检查 context 是否存在,只有在 Activity 调用了 onCreate 才存在。
if (getBaseContext() == null) {
throw new IllegalStateException(
"System services not available to Activities before onCreate()");
}
// 针对 WINDOW_SERVICE 和 SEARCH_SERVICE 可用直接返回相关服务实例。
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
ensureSearchManager();
return mSearchManager;
}
// 返回其他类型的系统服务,LayoutInflater 会走到这里。
return super.getSystemService(name);
}
复制代码
在Activity
中返回了WINDOW_SERVICE
和SEARCH_SERVICE
两种特殊类型的系统服务,其他类型的服务则继续调用super.getSystemService()
获取,这里的super
指的是ContextThemeWrapper
,转到这里继续分析:
@Override
public Object getSystemService(String name) {
// 在获取 LayoutInflater 实例时传入的名字就是 LAYOUT_INFLATER_SERVICE,此时会走到这里。
if (LAYOUT_INFLATER_SERVICE.equals(name)) {
if (mInflater == null) {
mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
}
return mInflater;
}
// 其他类型的系统服务继续调用 getSystemService 来获取服务实例。
return getBaseContext().getSystemService(name);
}
复制代码
ContextThemeWrapper.getSystemService
也没有真正返回服务实例,而是继续调用LayoutInflater.from()
:
/**
* Obtains the LayoutInflater from the given context.
*/
public static LayoutInflater from(Context context) {
// 调用 Context.getSystemService 获取 LayoutInflater 实例。
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 获取失败则抛出异常。
if (LayoutInflater == null)