Android系统启动
分析的源码基于android-8.0.0_r4
《安卓进阶解密》读书笔记
Android系统启动
在Android系统启动的流程中,主要介绍下面几点
init
进程启动过程Zygote
进程启动过程SystemServer
进程启动过程Launcher
启动过程
其中,init、Zygote、SystemServer
进程启动的关系密切,这里先给出流程图
Launcher
启动的部分时序图如下
init进程启动过程
init
进程是Android系统中用户空间的第一个进程,进程号为1
在init
进程启动之前,会先做下面几件事情
- 启动电源以及系统启动
- 执行引导程序BootLoader
- Linux内核启动
- init进程启动
当我们按下启动电源时,系统启动后会加载引导程序,引导程序又启动Linux内核,在Linux内核加载完成后,第一件事就是要启动init进程.
init进程启动主要做的事情
- 创建和挂载启动所需的文件目录
- 初始化和启动属性服务
- 解析
init.rc
配置文件并启动Zygote
进程
大致过程
先查看init
进程的入口函数main,在system/core/init/init.cpp
下
int main(int argc, char** argv) {
...
//1.创建和挂载启动所需的文件目录
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
...
//2.对属性服务进行初始化
property_init();
...
//3.设置子进程信号处理函数
signal_handler_init();
//4.启动属性服务
start_property_service()
...
if (bootscript.empty()) {
//5.解析init.rc配置文件
parser.ParseConfig("/init.rc");
...
}else{
...
}
...
while(true){
...
//6.重启死去的进程
restart_processes();
...
}
}
-
第2、4步:在Windows中,有注册表管理器,注册表的内容用于记录用户、软件的一些使用信息。Android也有类似的机制,称为属性服务,用户可以读取属性的信息,也可以添加属性,或者更新属性值
-
第3、6步:如果有子进程异常退出,第3步设置的子进程信号处理函数,会清除子进程相关的信息,并重启子进程的部分服务,可以防止子进程变成"僵尸进程",而子进程本身会在第6步重启
-
第5步:解析
init.rc
配置文件
解析与启动
解析:解析init.rc
文件
启动:启动Zygote
init.rc
是由Android初始化语言(Android Init Language)编写的脚本,包含5种类型的语句:Action、Command、Service、Option、Import。这里分析Zygote
相关的,Zygote
的启动脚本对应的是Service类型语句,Service类型语句格式如下
# <name> service的名字
# <pathname> 执行程序路径
# <argument> 传递参数
# <option> service的修饰符,它将影响服务何时、如何启动service
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
以64位处理器为例,Zygote
对应的启动脚本为init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
可以获取到的信息
- 服务的名称为zygote
- 执行程序的路径为/system/bin/app_process64
- 服务的classname为main
Zygote
重启时,要重启一些进程相关服务(onrestart restart xxx
)- ...
在init.zygote64.rc
解析完成之后,会将Zygote
对应的Service,添加到Service链表里,在system/core/init/service.cpp
中,如下
void ServiceManager::AddService(std::unique_ptr<Service> service) {
...
services_.emplace_back(std::move(service));
}
service_
就是Zygote
对应的Service
接着,在init.rc
中有Command类型的语句,用于启动Zygote
,最终会调用到Service
类的Start
方法,在system/core/init/service.cpp
中
bool Service::Start() {
...
//如果子进程没有启动,则调用fork函数创建子进程
pid = fork();
//子进程得到的pid == 0,下面if语句中的代码会在子进程中执行;init进程不会执行下面的if语句
if (pid == 0) {
...
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
...
}
...
}
...
}
调用execve
后,Service子进程就会启动,进入Service的main函数中,Zygote
的执行程序路径为/system/bin/app_process64
,对应文件frameworks/base/cmds/app_process/app_main.cpp
,所以会进入app_main.cpp
的main函数中,接下来就进入Zygote
的进程启动了~~
Zygote进程启动过程
Zygote
也称为孵化器,Android系统中,Dalvik虚拟机(DVM)和ART、应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote
进程来创建的。- 应用程序进程与SystemServer进程,均由
Zygote
进程Fork所得,由于Zygote
进程在启动时会创建DVM或者ART,因此通过Fork所创建的应用程序进程和SystemServer进程,可以在内部获取一个DVM或者ART的实例副本,避免启动虚拟机或加载系统资源等耗时操作
Zygote
进程启动共做了如下几件事
- 创建AppRuntime并调用其start方法,启动
Zygote
进程 - 创建Java虚拟机并为Java虚拟机注册JNI方法
- 通过JNI调用ZygoteInit的main函数进入
Zygote
的Java框架层 - 通过
registerZygoteSocket
方法创建服务器端Socket,并通过runSelectLoop
方法等待AMS的请求来创建新的应用程序进程 - 启动SystemServer进程
启动入口
在「init进程启动过程 - 解析与启动」笔记的最后,谈到了Zygote
进程启动了,接下来看下frameworks/base/cmds/app_process/app_main.cpp
的main方法
class AppRuntime : public AndroidRuntime{
...
}
#if defined(__LP64__)
...
static const char ZYGOTE_NICE_NAME[] = "zygote64";
#else
...
static const char ZYGOTE_NICE_NAME[] = "zygote";
#endif
int main(int argc, char* const argv[]){
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
bool zygote = false;
bool startSystemServer = false;
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
//1 如果当前运行在Zygote进程中,则将zygote设置为true
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
//如果当前运行在SystemServer进程中,则将startSystemServer设置为true
startSystemServer = true;
} ...
}
...
if (zygote) {
//2 如果运行在Zygote进程中
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} ...
}
- 注释1:为什么要判断当前运行的进程是不是
Zygote
进程呢?因为Zygote
是通过Fork来创建子进程的,由于Zygote
进程和子进程共享同一份代码空间,所以子进程的代码也是有可能执行到while(i < argc){...}
处的,所以这里要做一个判断 - 注释2:如果运行在
Zygote
进程,就调用AppRuntime的start方法,该方法的实现在它的父类AndroidRuntime中
Native->Java
# classname:com.android.internal.os.ZygoteInit
# args
# zygote:true
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
...
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
//1.启动Java虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
//2.为Java虚拟机注册JNI方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
//3.将className的"."替换为"/"
char* slashClassName = toSlashClassName(className);
//4.找到ZygoteInit的Class
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
} else {
//5.找到ZygoteInit的main方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
} else {
//6.通过JNI调用ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
...
}
}
}
- 注释6:为什么这里要使用JNI呢?因为ZygoteInit的main方法是由Java编写的,当前的运行逻辑在Native中,这时候需要通过JNI来调用Java。这样
Zygote
就从Native层进入了Java框架层,此前是没有任何代码进入Java框架层的,换句话说是Zygote
开创了Java框架层
ZygoteInit的main方法
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
...
try {
...
//1.创建一个Server端的Socket,socketName的值为"zygote"
zygoteServer.registerServerSocket(socketName);
if (!enableLazyPreload) {
...
//2.预加载类和资源
preload(bootTimingsTraceLog);
...
}
...
if (startSystemServer) {
//3.启动SystemServer进程
startSystemServer(abiList, socketName, zygoteServer);
}
Log.i(TAG, "Accepting command socket connections");
//4.等待AMS请求创建新的应用程序进程
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
}catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
ZygoteInit的main方法主要做了4件事情
- 创建一个Server端的Socket
- 预加载类和资源
- 启动SystemServer进程
- 等待AMS请求创建新的应用程序进程
这里"预加载类和资源"的部分不进行分析,"启动SystemServer进程"后面会分析
1.创建一个Server端的Socket
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
void registerServerSocket(String socketName) {
if (mServerSocket == null) {
int fileDesc;
//拼接Socket的名称
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//得到Socket的环境变量的值
String env = System.getenv(fullSocketName);
//将Socket环境变量的值转换为文件描述符的参数
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
//创建文件描述符
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
//创建服务端SOcket
mServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
- 这里拼接Socket的名称时,ANDROID_SOCKET_PREFIX的值为"ANDROID_SOCKET_",所以fullSocketName的值为"ANDROID_SOCKET_zygote"
3.启动SystemServer进程
后面分析~~
4.等待AMS请求创建新的应用程序进程
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
//将前面创建的mServerSocket的文件描述符添加到列表fds中
fds.add(mServerSocket.getFileDescriptor());
//peers添加一个null,使得初始的时候fds和peers的size都为1
peers.add(null);
while (true) {
//通过遍历将fds的信息转移到pollFds数组中
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
/*
* i==0的时候,说明当前fds里面只有mServerSocker的文件描述符,说明此时
* 没有"创建应用程序进程"的请求,通过acceptCommandPeer方法等待连接
*/
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
/*
* i不等于0,说明这是一个"创建应用程序进程"的请求,通过调用ZygoteConnection
* 的runOnce方法,来创建一个"新的应用程序进程"
*/
boolean done = peers.get(i).runOnce(this);
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
这里等待"创建应用程序进程"的请求,是在无限循环while(true){...}
里面实现的,一个可能的执行顺序如下
- 当前没有"创建应用程序进程"的请求,那么pollFds的length为1,则for循环里面的i等于0,那么会调用
acceptCommandPeer
方法
/**
* Waits for and accepts a single command connection. Throws
* RuntimeException on failure.
*/
private ZygoteConnection acceptCommandPeer(String abiList) {
try {
return createNewConnection(mServerSocket.accept(), abiList);
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
从方法的注释可以知道,此时会阻塞等待一个连接到来
- 当有一个连接请求到来时,会向
fds
和peers
增加对应的元素,此时程序继续往下走,for循环结束,又进入while语句,这时for (int i = pollFds.length - 1; i >= 0; --i) {...}
,pollFds.length的值为2,也就是说,i的值先是1,那么就会走到下面的else
语句,调用ZygoteConnection
的runOnce
方法,来创建一个"新的应用程序进程",然后在fds
和peers
移除相应的元素,接着进入下一层的for循环,这时i的值为0,又是等待连接的到来,重复之前的步骤
这个runSelectLoop里面的执行顺序是自己的理解,不知道对不对
SystemServer进程启动过程
SystemServer
进程主要用于创建系统服务,我们熟知的AMS、WMS和PMS都是由它来创建的
SystemServer
进程被创建后,主要做了如下工作
- 启动Binder线程池,这样就可以与其他进程进行通信
- 创建SystemServiceManager,其用于对系统的服务进行创建、启动和生命周期管理
- 启动各种系统服务
前面谈到在Zygote
进程中,会启动SystemServer
进程,也就是在ZygoteInit
的main
方法的第三步,再放一下ZygoteInit
的main
方法
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
...
try {
...
//1.创建一个Server端的Socket,socketName的值为"zygote"
zygoteServer.registerServerSocket(socketName);
if (!enableLazyPreload) {
...
//2.预加载类和资源
preload(bootTimingsTraceLog);
...
}
...
if (startSystemServer) {
//3.启动SystemServer进程
startSystemServer(abiList, socketName, zygoteServer);
}
Log.i(TAG, "Accepting command socket connections");
//4.等待AMS请求创建新的应用程序进程
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
}catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
进程启动
ZygoteInit
的startSystemServer
的实现如下
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
throws Zygote.MethodAndArgsCaller, RuntimeException {
...
//1.args数组用于保存SystemServer的启动参数
String args[] = {
"--setuid=1000",
"--setgid=1000",
...
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//2.将args数组封转为ZygoteConnection.Arguments对象,供后面Fork进程的时候使用
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
//3.Fork进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/*
* 4.Fork出来的SystemServer进程的pid==0,会执行下面的If语句,而Zygote进程不会执行下面
* 的If语句
*/
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
//5.关闭Zygote进程创建的Socket
zygoteServer.closeServerSocket();
handleSystemServerProcess(parsedArgs);
}
return true;
}
-
第3步:
Zygote.forkSystemServer
,内部会调用Native方法nativeForkSystemServer
,该方法最终会通过fork函数,在当前进程(Zygote
进程)创建一个子进程(SystemServer
进程) -
第5步:
SystemServer
进程由Zygote
进程Fork而来,所以SystemServer
进程也复制了Zygote
进程的地址空间,因此也会得到Zygote
进程创建的mServerSocket
,但是该Socket
对于SystemServer
进程没有用处,所以在注释5处,将其关闭
接着看下ZygoteInit
的handleSystemServerProcess
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
throws Zygote.MethodAndArgsCaller {
...
if (parsedArgs.invokeWith != null) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
//创建PathClassLoader
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
//调用zygoteInit方法,并且传入parsedArgs的剩余参数
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
- parseArgs:前面提到,这是SystemServer的启动参数的包装
ZygoteInit
的zygoteInit
public static final void zygoteInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
...
//1.启动Binder线程池
ZygoteInit.nativeZygoteInit();
//2.进入SystemServer的main方法
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
- 第1步:这里会通过JNI的方式,调用Native层的代码,最终通过Native层的AppRuntime,启动Binder线程池
抛出异常-清理栈帧
接着看RuntimeInit
的applicationInit
protected static void applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
...
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
RuntimeInit
的invokeStaticMain
# className:SystemServer
# classLoader:前面创建的PathClassLoader
private static void invokeStaticMain(String className, String[] argv, ClassLoader
classLoader) throws Zygote.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} ...
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} ...
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new Zygote.MethodAndArgsCaller(m, argv);
}
这段代码很有意思,首先是通过Class.forName
,找到SystemServer
对应的Class对象,接着通过反射,获取SystemServer
的main
方法,然后将该方法包装到异常MethodAndArgsCaller
中,将其抛出,MethodAndArgs Caller
定义如下
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} ...
}
}
抛出的MethodAndArgsCaller
会在前面提到的ZygoteInit
的main
方法中捕获到
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
...
try {
...
if (startSystemServer) {
//3.启动SystemServer进程
startSystemServer(abiList, socketName, zygoteServer);
}
Log.i(TAG, "Accepting command socket connections");
//4.等待AMS请求创建新的应用程序进程
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
}catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
-
为什么
SystemServer
进程的异常可以抛到这里呢?因为SystemServer
进程由Zygote
进程Fork而来,两个进程进程共享同一代码空间 -
caller.run()
:这里会执行MethodAndArgsCaller
的run
方法,通过反射调用到了SysetmServer
的main
方法
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} ...
}
那么,现在有一个问题,为什么不直接在RuntimeInit
的invokeStaticMain
里调用SystemServer
的main
方法,而是这么大费周章呢?原因是这种抛出异常的处理会清除所有的设置过程需要的堆栈帧,让SystemServer
的main
方法看起来像是SystemServer
进程的入口方法一样,而实际上,在调用SystemServer
的main
方法之前,已经做了很多的准备工作.
好NB的一个操作!!太秀了!
启动系统服务
接着看SystemServer
的main
方法
public static void main(String[] args) {
new SystemServer().run();
}
看SystemServer
的run
private void run() {
try {
...
//创建消息Looper
Looper.prepareMainLooper();
// 加载动态库libandroid_servers.so
System.loadLibrary("android_servers");
performPendingShutdown();
//创建系统的Context
createSystemContext();
//创建SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
// Start services.
try {
traceBeginAndSlog("StartServices");
//启动引导服务
startBootstrapServices();
//启动核心服务
startCoreServices();
//启动其他服务
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
...
} finally {
traceEnd();
}
...
}
- SystemServiceManager:会对系统服务进行创建、启动和生命周期管理
- 官方把系统服务分为三种类型:引导服务、核心服务、其他服务
Launcher启动过程
系统启动的最后一步是启动Launcher
应用程序,它用来显示系统中已安装的应用程序。SystemServer
在启动系统服务的时候,会先启动AMS
,然后会启动PackageManagerService
,PackageManagerService
启动后会将系统中的应用程序安装完成,AMS
会在上面提到的startOtherServices
方法中启动Launcher
,Launcher
启动过程中会向PackageManagerService
请求系统中已安装的应用程序的信息
Launcher
作用有两点
- 作为Android系统的启动器,用于启动应用程序
- 作为Android系统的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件
启动过程
Launcher
启动的部分时序图如下
在时序图之后,还有下面的几步
- 在调用完
AMS
的startHomeActivityLocked
后,AMS
会调用ActivityStarter
的startHomeActivityLocked
- 在
startHomeActivityLocked
方法中,会将Launcher
放入ActivityStackSupervisor
的HomeStack
变量中 - 接着
ActivityStarter
调用自身的startActivityLocked
方法来启动Launcher
- 剩余的过程和
Activity
的启动过程类似,最终进入Launcher
的onCreate
方法中,Launcher
就完成了启动
应用图标显示过程
应用图标的显示过程可以分为以下几步
- 在
Launcher
的onCreate
中,获取LauncherAppState
的实例,通过LauncherAppState
的实例,获取到LauncherModel
对象的引用,该LauncherModel
持有Launcher
的弱引用 - 在
Launcher
的onCreate
中,调用LauncherModel
的startLoader
方法 - 插入:在
LauncherModel
中,有一个静态变量HandlerThread sWorkerThread
和一个静态变量Handler sWorker
,sWorker
可以向sWorkerThread
发送消息,让任务执行在子线程中 - 在
LauncherModel
的startLoader
方法中,会构建一个对象LoaderTask
,LoaderTask
实现了Runnable
接口,通过sWorker
将LoaderTask
代表的任务推送到子线程中去执行
LoaderTask是LauncherModel的内部类,定义如下
private class LoaderTask implements Runnable {...}
LoaderTask
的任务是"加载工作区信息"和"绑定工作区信息",接着会调用loadAllApps
方法- 在
loadAllApps
方法中,会通过主线程的Handler
,将一个Runnable
任务推送到主线程中执行,这个任务中,会调用Launcher
的bindAllApplications
方法 - 在
bindAllApplications
方法中,会把"应用列表的信息"传给AllAppsContainerView mAppsView
,AllAppsContainerView
实际上是RelativeLayout
的子类,它会保存"应用列表的信息",等到mAppsView
的onFinishInflate
方法被调用的时候,mAppsView
会通过findViewById
找到它内部的AllAppsRecyclerView
,这实际上是RecyclerView
的一个子类,通过为它设置设配器、"应用列表的信息"等,应用程序快捷图标的列表就会显示在屏幕上
onFinishInflate
是View的方法
步骤就是这样,具体的过程可以看书~~
参考
《安卓进阶解密》