1.Android程序流程
众所周知,我们的java程序想要开启需要依赖于main方法,也就是我们的程序入口(主线程)进入,但是在我们日常开发android程序的过程当中我们并没有发现main方法的存在,那么android当中的是如何开始运行的?
熟悉的朋友们可能都知道在android当中存在一个叫做ActivityThread的类,这个类代表的是android当中的主线程,而在这个类当中我们看到了比较熟悉的main方法,那么现在是否可以认为我们的android在打开app时是首先调用的是当前这个类的main,也就是此处为我们的启动点:
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
这里省略掉部分代码...............
Looper.prepareMainLooper();//这里开启主线程的Looper创建
ActivityThread thread = new ActivityThread();//主函数再次开启一个Activity线程
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();//这里开启主线程的消息轮训
throw new RuntimeException("Main thread loop unexpectedly exited");
}
OK,我们开始进入thread.attach(false)这个方法中查看做了什么:
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
这里省略掉部分代码...............
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//这个IActivityManager是Activity管理接口,
final IActivityManager mgr = ActivityManager.getService();那么这个mgr得到的到底是什么?继续看下一步
try {
//这里调用attachApplication()这个方法
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
这里省略掉部分代码...............
}
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
}
进入ActivityManager中查看getService()这个方法:
/**
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
在这个当中,里面调用了的系统的ActivityManagerService这个服务,并且给出了一个Binder接口
了解Binder机制的小伙伴看到这里应该很眼熟,在图中的create方法中进行了一个跨进程的相关操作
1:获得系统的IBinder的实现类
2:将系统(服务端)的Binder对象转换成客户端可以使用的接口类对象
也就是说getService这个方法所返回的对象其实就是和系统进行跨进程通信的,从对象的类名称可知是Activity的管理类。mgr通过attachApplication方法和mAppThread进行了绑定,mAppThread的类是ApplicationThread,父类为IApplicationThread.Stub,和Binder中的Stub的作用一样,用来接收系统(服务端)发过来的跨进程消息。这也是为什么我们讲Activity是跨进程访问的原因。
attachApplication方法另外一个作用是在这里的作用其实实际上是ActivityThread通过attach获取到后,然后将applciationThread将其关联,把activity相关信息存储在applciationThread里面,apllicationThread的类为activity的各种状态做了相对应的准备工作。如下为attachApplication方法的具体源码:
这个时候我们需要关注,ApplicationThread(ApplicationThread这个类是在ActivityThread中的内部类)当中做了什么?
当我们打开ApplicationThread中我们会看到一堆的schedle方法,这些方法的名称其实就可以给我们表明,代表的是在执行Activity的某种状态时调用的计划执行方法,这时我们会看到一个scheduleLaunchActivity方法,表示计划加载时调用的。这里我们发现了一个很有意思的事情:
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();//这个对象就是我们的Activity
r.token = token;
r.ident = ident;
r.intent = intent;
//...一系列的赋值操作
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);//将当前我们创建的Activity发送了出去
}
当走到这里我们会发现最终我们调用的是Handler的消息通信机制,也就是说,在这里我们可以总结一下,当Activity状态改变时,都会有对应的一个消息发送出去,而接收这里,我能发现通过发送时不同的状态,这边调用了不同的handlerXXXActivity方法。
在ActivityThread类中有一个Handler类名为H,该类就是用来处理不同的发送消息,以便改变Activity状态等操作的,如下:
public vo