android开发之源码级分析(系统启动流程 & Handler消息机制 & AsyncTask机制)
Android系统启动流程
Android启动过程:系统引导Linux内核启动,内核启动时会加载Linux的各种设备驱动和数据结构,驱动加载完毕,Android系统才开始启动,启动过程中,系统加载第一个用户级别的进程:init,而launcher(桌面进程)是Android系统启动完毕之后,加载的第一个上层应用的进程。
Bootloader:引导程序 – DOS的启动盘
Linux Kernel:内核启动
Android:系统启动
init.c – 源码在system\core\init目录下
查看init.c代码,看main函数
init main(int argc,char **argv) { ... //执行Linux指令 mkdir("/dev",0755); mkdir("/proc",0755); mkdir("/sys",0755); ... //解析执行init.rc配置文件 init_parse_config_file("/init.rc");}
init.rc – 源码在system\core\rootdir – 包含非常多的可执行指令
播放开机动画:
service bootanim /system/bin/bootanimation user graphics group graphics disabled oneshot
启动孵化器进程:
service zygote /system/bin/**app_process** -Xzygote /system/bin -- zygote -- start-system-server socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd
app_process文件夹下的:源码在frameworks\base\cmds\app_process
app_main.cpp:启动了ZygoteInit服务!
int main(int argc, const char* const argv[]) { ... if (i < argc) { arg = argv[i++]; if (0 == strcmp("--zygote", arg)) { bool startSystemServer = (i < argc) ? strcmp(argv[i], "--start-system-server") == 0 : false; setArgv0(argv0, "zygote"); set_process_name("zygote"); runtime.start("com.android.internal.os.ZygoteInit", startSystemServer); ...}
在ZygoteInit.java中
- main()中:
public static void main(String argv[]) { try { ... **preloadClasses();** ... } catch (RuntimeException ex) { }}
- preloadClasses():进行预加载类
private static void preloadClasses() { ... //解析PRELOADED_CLASSES文件,把该文件中定义好的1835个类全部预加载进来! InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(PRELOADED_CLASSES); //PRELOADED_CLASSES包含很多的java类!包括ActivityThread.java... ...}
- 回到ZygoteInit.java中的main()中:
public static void main(String argv[]) { try { ... if (argv[1].equals("true")) { **startSystemServer();** //启动系统服务! } else if (!argv[1].equals("false")) { throw new RuntimeException(argv[0] + USAGE_STRING); } ... } catch (RuntimeException ex) { }}
- startSystemServer() – 启动系统服务
/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", **"com.android.server.SystemServer"**, }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); /* * Enable debugging of the system process if *either* the command line flags * indicate it should be debuggable or the ro.debuggable system property * is set to "1" */ int debugFlags = parsedArgs.debugFlags; if ("1".equals(SystemProperties.get("ro.debuggable"))) debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER; /* Request to fork the system server process */ **pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities);** } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } ... }
SystemServer.java中的mian()方法中
public static void main(String[] args) { ... //加载动态链接库 **System.loadLibrary("android_servers");** **init1(args);** ...}
加载完成之后,在main()方法中又调用了init1(args);方法,显然发现init1()是一个本地方法,那么init1()方法有可能在动态链接库中;因此就找到了com_android_server_SystemServer.cpp:
com_android_server_SystemServer.cpp:源码存放在frameworks\base\services\jni目录下
namespace android {.../* * JNI registration. */static JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ { **"init1"**, "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },};...};
函数也是可以用指针的!因此我们可以知道init1的函数指针就是(void*) android_server_SystemServer_init1 ;这样的话也说明了init1由函数指针代替,因此init1执行的时候就会去执行android-server_SystemServer_init1()方法!那么在com_android_server_SystemServer.cpp中就不难发现有这样一个方法了!
namespace android {...static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz){ system_init();}...};
那么在android_server_SystemServer_init1()方法中会去调用system_init()方法:
namespace android {extern "C" int system_init();...};
该方法是一个抽象的方法,因此需要子类去覆写该方法!那么再去搜那里覆写了该方法;最后发现System_init.cpp类中覆写了这个方法:
System_init.cpp:
extern "C" status_t system_init(){ ...... //运行静态方法,要运行SystemServer类中的**init2()**方法 runtime->callStatic("com/android/server/SystemServer", "init2"); ......}
来到SystemServer类中的init2()方法:
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start();}
该方法创建了服务线程,并开启了线程,那么这样的话,就去看看线程到底干了些什么!去看看线程中的run()方法,在run()方法中,给ServiceManager添加了好多SystemService。这也是我们之所以能在java程序中使用getSystemService()方法能得到自己想要的Service,因为都在这里添加完成了。你尽管拿!ServerThread类就在本类当中,而run()因此也就在本类当中!
class ServerThread extends Thread { ... @Override public void run() { ... ((ActivityManagerService)ActivityManagerNative.getDefault()).**systemReady**(new Runnable() { public void run() { ... } }); ... } ...}
在run()方法中,有一个重点:ActivityManagerService类中的systemReady()方法!
public void systemReady(final Runnable goingCallback) { ... //mMainStack:ActivityTask任务栈 **mMainStack.resumeTopActivityLocked(null);**}
ActivityTask.java中resumeTopActivityLocked方法中:
final boolean resumeTopActivityLocked(ActivityRecord prev) { ... // Launcher... if (mMainStack) { return mService.startHomeActivityLocked(); } ...}
Handler消息机制
主线程有一个消息队列(MessageQueue),用来存储子线程中的handler.sendMessage()发送过来的消息,之后如果MessageQueue一旦有消息,那么就会去唤醒Looper.loop()轮询器,轮询器就会不断的检查MessageQueue有没有消息,如果有消息,那么就交给用户自己定义的Handler对象,去调用handler对象中的handleMessage()方法来处理消息。
消息的创建:使用handler.obtionMessage(),但最终会调用Message类中的obtion()方法,来创建Message对象。
public final Message obtainMessage(){ return Message.obtain(this);}
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message();}
前提:
①、首先来看MessageQueue中的消息,按照队列的思想,先进先出去处理每一个消息
②、消息对象有一个成员属性:Message next。next本身也是一个消息。
a消息有一个成员属性next,而next也是一个消息,那么就是a指向b,b指向c–单链表的形式来维护消息的,而不是消息队列来维护的!因此消息是由消息自己来维护的,而不是靠消息队列来维护。
分析Message.obtain()方法中的代码:
if(sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m;}
①. Message m = sPool;
②. sPool = m.next;
③. m.next = null;
④. sPoolSize–;消息池中的消息被拿走了一条,所以总数减一。
⑤. return m;把a消息拿出去,a就离开了消息池,而sPool依然指向第一条消息。
handler创建:任何一个应用程序启动的时候,ActivityThread都会被创建。
ActivityThread中的main()方法中:
public static final void main(String[] args) { ... Looper.prepareMainLooper(); //创建轮询器 ... ActivityThread thread = new ActivityThread(); ... Looper.loop(); //开启轮询器,开始轮询,不断的检查消息队列是否有消息 ... }}
- 在Looper.prepareMainLooper()中:
public static final void prepareMainLooper() { prepare(); ...}
在prepare()中:
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(**new Looper()**); //创建轮询器,同时将会创建MessageQueue(消息队列)}
- 在Looper.loop()中:
public static final void loop() { ... while (true) { //主线程 Message msg = queue.next(); // might block -- 如果消息队列没有消息,就会阻塞休眠 ... }}
为什么阻塞休眠?
因为内存中的一块空间存放了特殊文件
消息队列中有消息不会唤醒主线程的,唤醒主线程的是管道,就是当你往消息队列中发送消息的时候,会往管道中写数据,这样才会唤醒主线程。
消息发送: Message对象中有一个long类型记录自己的发送时间。
使用handler.sendMessage();通过handler对象调用各种方法来发送消息,不管你调用哪个方法,其实最终调用的都是sendMessageAtTime(),但前提是创建了Handler对象,一旦创建了对象必将调用其构造。
Handler对象构造方法:
public Handler(Looper looper) { mLooper = looper; mQueue = looper.mQueue; //从looper对象中拿到已创建好的MessageQueue对象 mCallback = null;}
sendMessageAtTime():
public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; MessageQueue queue = mQueue; //从looper对象中拿到已创建好的MessageQueue对象 if (queue != null) { msg.target = this; //绑定当前处理器(handler) sent = **queue.enqueueMessage(msg, uptimeMillis);**//通过MessageQueue对象调用其enqueueMessage()方法 } else { ... } return sent;}
enqueueMessage():
final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } **final boolean needWake; //是否需要唤醒** synchronized (this) { ... msg.when = when; //时间 Message p = mMessages; //消息队列里的第一条消息 if (p == null || when == 0 || when < p.when) { msg.next = p; mMessages = msg; ... } } if (needWake) { nativeWake(mPtr); //唤醒主线程 } return true;}
第一种情况:p == null;
第二种情况:when = 0;
msg.next = p;
mMessage = msg;
第三种情况:when < p.when;//说明你传进来的消息的事件小于消息队列中的第一条消息的时间。
如果三种情况都不满足,那么:
来了一条消息:准备往消息队列中去插
p = p.next;//此时此刻p指向b
while(p.when < when);//p.when:表示b的时间,如果你传进来的消息的时间还比消息队列中的b消息的时间还大,那么就p又指向c消息,这样一次一次的进行对比:
一直这样,终于消息队列中的消息的时间,比你传进来的消息的时间大,那么就插入到c消息的前面。
如果此时,c消息的时间比你传过来的消息的时间大,那么就:
prev = p;
p = p.next;
msg.next = prev.next;
prev.next = msg;
Looper轮询器:分发处理消息
①、Message对象中有一个Handler类型的成员变量target,这个target是记录此消息对象是由谁创建的。
②、多个Handler给同一个消息队列发送消息。
Looper.loop() – > next() – > dispatchMessage() – > handleMessage();
AsyncTask机制
①、创建AsyncTask对象:
要执行execute()方法,首先就得创建AsyncTask对象,那么就会去执行其AsyncTask的构造方法,在其构造方法中:只是创建了WorkerRunnable对象,并没有去调用call(),因此不会去执行doInBackground()方法。
public AsyncTask() { mWorker = new WorkerRunnable<Params, Result>() {//创建WorkerRunnable对象,是Callable的实现类。 public Result call() throws Exception { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); return doInBackground(mParams);//该方法目前还不会被执行,因为没有人调用call()方法。 } }; //把WorkerRunnable对象传给了Future对象,作为其构造方法的参数。FutureTask是RunnableFuture的实现类,它的爷爷是Runnable。 mFuture = new FutureTask<Result>(mWorker) { ...... }; ......}
②、在Future类的构造函数中:
③、创建了Sync对象,执行其构造方法:
private final Callable<V> callable;Sync(Callable<V> callable) { this.callable = callable;//callable就是通过层层传递过来的WorkerRunnable对象。}
④、执行execute():
⑤、在execute()方法中的sExecutor.execute(mFuture)://sExecutor:是线程池。
private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor( CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
那么用线程池的sExecutor.execute(mFuture)方法去执行一个Runnable对象,线程池会开启子线程去执行Runnable的run()方法。
FutureTask中的run()方法:
调用innerRun():
使用Sync中的成员变量callable去调用了其自身的callable.call()方法,而callable就是一层一层传入过来的WorkerRunnable对象,这样调用call()方法就是调用WorkerRunnable中自身的实现好的call()方法,与此同时也就调用了call()方法中的doInBackground()方法,而doInBackground()方法是在子线程中被调用的。
那么,doInBackground()方法返回来的结果,赋值给了innerRun()中的result,而result有作为了set(result)参数传给了set()方法:
又调用了内部类Sync中的innerSet()方法:
而方法中有调用了done()方法,而done方法我们可曾写过:
在AsyncTask构造函数中曾创建了FutureTask对象并覆写了done()方法:
而sendToTarget()方法中又调用了sendMessage()方法:
同时target就是sHandler,那么将消息发送到消息队列当中,消息最终要被处理就会调用哪个发送消息的handler来处理,这里发送消息的就是sHandler,而sHandler又是哪里来的呢?
AsyncTask的内部类:
private static final InternalHandler sHandler = new InternalHandler();
MESSAGE_POST_RESULT:将会调用finish()方法:
这样就调用了onPostExecute(result);//result:就是doInBackground()所返回的结果。
All in all,because just begun!
更多相关文章
- TextView支持的XML属性及相关方法
- 详解Android应用中使用TabHost组件进行布局的基本方法
- Android 之 Looper、MessageQueue、Handler 与消息循环
- 简述Android消息机制及解惑
- Android的广播机制——Broadcast Reciver
- drawRoundRect方法:绘制圆角矩形
- Android不同版本获取当前wifi信息方法