前言
一个app的程序是怎么启动的?入口在哪里?
据说ActivityManagerServices很吊,Why?
Activity生命周期究竟是谁调用的?
Application又是在哪里初始化的?onCreate又是如何被调用的?
面试官经常会问:为何主线程使用looper.loop不会卡死界面?
等等..
是否是一直有这样的疑问?很懵逼对不对 - - ,那咱们就站在巨人的丁丁上来解决一下这些问题,若是文中出现一些错误,还望指正,互相学习java
主要流程
你们都知道 Android是基于Linux系统的,而在Linux中,全部的进程都是由init进程直接或者是间接fork出来的,当我开机的时候init进程就会fork出一个Android的第一个新的进程
Zygote,中文翻译过来要”受精卵”,一个颇有意识的名字。为何这么说呢,当咱们Zygote进程跑起来后,Android为了实现实现资源共用和更快的启动速度,经过Zygote进程直接去fork出一些子进程,这就是为何要”受精卵”的缘由,也就是咱们的app所有都是基于Zygote上的 ,没有Zygote就没有咱们,当Zygote初始化完成以后,首先会fork它的第一个子进程SystemServer,这个类很是的重要,为何这么说呢?由于系统里面重要的服务都是在这个进程里面开启的,好比ActivityManagerService、PackageManagerService、WindowManagerService等等,有木有以为似曾相识
当SystemServer跑起来后,这些重要的服务也会随之建立,系统初始化完成以后咱们就会进到系统桌面->Launcher,其实Launcher也是一个app,它继承自Activity,当咱们点击桌面上的app后,系统就会为咱们的app建立一个进程,而后启动咱们App的第一个类ActivityThread,其实说到底咱们的app就是一个main函数,也就是启动了ActivityThread.main()。咱们重点来看下这个类android
App的程序入口
都说主线程更新ui,主线程不能有耗时操做,主线程是在哪里建立的呢?咱们来看下ActivityThread.main()。面试
public static void main(String[] args) {
....
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);app
Process.setArgV0("<pre-initialized>");
//建立主线程Looper
Looper.prepareMainLooper();ide
ActivityThread thread = new ActivityThread();
thread.attach(false);函数
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}oop
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}post
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//主线程消息循环
Looper.loop();学习
throw new RuntimeException("Main thread loop unexpectedly exited");
}
为何主线程使用Looper.loop()不会卡死界面
首先咱们要明白一点,主线程也是一个线程,也是有他的生命周期的,当咱们new Thread()后执行完里面的代码也就意味着这个线程的结束,刚说了主线程也是线程,若是咱们的代码一下就执行完了,那么咱们这个app的功能还能执行吗? 我还没开始呢,你咋就结束了?这样多不持久,Android为了解决这个问题,使用的Looper循环,了解Handler的机制的童鞋,会知道在处理消息的时候使用了Looper.loop()方法,而且在该方法中进入了一个死循环
同时Looper.loop()方法是在主线程中调用的,那么为何没有卡死界面呢?ui
线程的生命周期
首先咱们要明白线程它也是有生命周期的,它的生命周期在于这个线程里面所要执行的代码执行完成,这个线程的使命也就完成了
主线程如何与子线程通讯
其次咱们要明白咱们主线程是如何跟子线程通讯(发消息)的
public class MainActivity extends AppCompatActivity {
Handler mHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
//初始化Looper对象 一个线程对应一个looper
Looper.prepare();
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i("test", "do somethings");
}
};
//开启消息循环
Looper.loop();
}
}).start();
findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHandler.sendEmptyMessage(1);
}
});
}
}
咱们主线程跟子线程就是这样通讯的,但是为何要 先Looper.prepare(),而后执行处理逻辑,最后Looper.loop();
咱们先来看看Looper.prepare()
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
sThreadLocal你能够理解成一个hashmap键值对,key就是咱们当前的Thread线程,value就是new Lopper出来的对象,sThreadLocal.get()若是不等于空的话 表示直接调用了prepare已经set进去了,就会抛出一个异常。也就是说一个线程只能对应一个looper,人家但是很专注的~,在来看看
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
//获取当前线程对应的Looper对象
final Looper me = myLooper();
if (me == null) {
//没有调用Looper.prepare()
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
//死循环,不断从消息队列取消息,有消息就直接处理消息
for (;;) {
//取出下一个消息
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
//当前没有消息,直接返回
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
//能走到这里,表示msg不为空,有消息要处理
//调用handler.dispatchMessage()处理消息
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
代码上注释也写的比较清楚了,咱们刚说了线程也是有生命周期的,咱们在线程里面建立了looper对象以后,new Handler()而后去处理消息,假如咱们Looper.loop()没有这个死循环,这个线程任务就执行完成了,那Handler里面还能收到消息吗?因此我就须要调用Looper.loop()一个死循环,不断去消息队列去取,而后咱们主线程发了消息后,Looper取到了消息,子线程里面的Handler也就天然可以处理消息这就是这个调用Looper.loop()的做用
主线程建立Handler的时候为何不用调用Looper.prepare(),Loop.loop()?
咱们在来看看AcivityThread源码
ActivityThread.java
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
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();
...
}
看到木有,在咱们app启动的时候,ActivityThread已经帮咱们作好了Looper消息循环,因此咱们在主线程new Handler()的时候就不用建立Looper,反而你再次调用Looper.prepare()还会报错,由于主线程已经建立了Looper对象了。
为何主线程不会卡死界面
理解了上面几个问题咱们就比较好理解了,首先,主线程也是线程,只不过这个线程是被系统建立的(就比如咱们本身建立了子线程同样),其次 Looper是不断的去消息队列里面取,取到消息就去处理消息,只要处理消息的操做不是耗时操做,就不会引发卡顿,其实Android的交互都是基于消息机制的分发,handler 能够发送消息,而后loop 里就分发消息而后就发给handler, 而后就执行到 H(Handler )里的对应代码。因此这些代码就不会卡死~,也就说循环消息并不会使起卡死,而真正会卡死的是咱们的处理消息,这也就是咱们主线程为何不能执行耗时操做的缘由。
举个栗子
讲到这里你可能还不是很能理解,那咱们就来举一个栗子~
咱们去作地铁或者作火车的时候都要去过安检,这个安检的机器就比如咱们的Looper对象,机器内部检测违禁品就比如是Handler,由于咱们要依次排队去放到机器上去检查,咱们一我的的行李物品就比做一个Message,多我的因此就组成了一个MessageQueue, 好,有了这些东西咱们就能够脑补整个运行过程了,首先若是要运行机器首先你的插插头吧?否则怎么通电->(Looper.prepare),通完点后你得按开关吧?(Looper.loop),由于运行很早,这个时候尚未人来安检,此时消息队列(MessageQueue)是空的,这个时候我过来安检,由于我是出去玩,因此带的东西比较少,这个时候我把个人包包(Message)放到了安检机器的韧带(MessageQueue)上面了,此时MessageQueue消息队列里面就有个人包包了,机器此时正在运转,
而后机器自动检测个人是否有违禁品(Handler.handleMessage),这个时候来了位大叔,带着很大一包东西(Message),放到了MessageQueue里,这个安检机器还在循环(Looper),当循环到这个大叔的大件后,大叔在另外一头等待了很久发现怎么都不出来,由于太大,检测须要时间(假设机器比较low),而这个等待的时间就是咱们所说的作了耗时操做致使ui卡顿。若是等了好久会致使不少乘客不满(ANR)。这个比喻可能不是很形象,可是话粗理不粗,这个只是个人我的理解
若是你们仍是不能理解的话,能够参考Android事件机制详细解读里面有更深刻的解读
ActivityThread.attach()
回归上一个话题,执行main函数的时候new ActivityThread(),执行了它的attach方法,咱们来看下attach方法
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
...
final IActivityManager mgr =ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {
@Override public void run() {
if (!mSomeActivitiesChanged) {
return;
}
Runtime runtime = Runtime.getRuntime();
long dalvikMax = runtime.maxMemory();
long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
if (dalvikUsed > ((3*dalvikMax)/4)) {
if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
+ " total=" + (runtime.totalMemory()/1024)
+ " used=" + (dalvikUsed/1024));
mSomeActivitiesChanged = false;
try {
mgr.releaseSomeActivities(mAppThread);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
});
} else {
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
android.ddm.DdmHandleAppName.setAppName("system_process",
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
ContextImpl context = ContextImpl.createAppContext(
this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
}
首先attach方法有一个boolean的变量system,传过来的是false,聪明的你一看就是这个意思,是不是系统应用 ,固然咱们不是,而后咱们会走到if里面,里面有一行比较关键的代码
final IActivityManager mgr = ActivityManagerNative.getDefault();
我点进去看下getDefault()函数
ActivityManagerNative.java
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
看注释说返回一个系统全局的ActivityManager,调用了gDefault.get(),咱们来看下这个gDefault变量看看是在哪里初始化的
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
ServiceManager.getService(“activity”)返回一个IBinder 这个Binder对象是谁呢?既然有getService,那么确定有addService,而且这个key是“activity”,咱们来看下是在哪一个类添加的
ActivityManagerService.java
public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(this));
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
"android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
synchronized (this) {
ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(app.pid, app);
}
updateLruProcessLocked(app, false, null);
updateOomAdjLocked();
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find android system package", e);
}
}
咱们看这一行代码
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
看下这个Context这个常量:
public static final String ACTIVITY_SERVICE = “activity”;
正好是刚才ServiceManager.getService()传过去的key, addService()的时候传过去一个this,也就是ActivityManagerService本身,那么getService()的时候返回的毫无疑问就是ActivityManagerService
咱们在回来看下ActivityThread.attach()方法
ActivityThread.java
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
咱们搞清楚调用ActivityManagerNative.getDefault()返回了IActivityManager类型的mgr,也就是ActivityManagerService以后 ,它调用了attachApplication,并传入了一个mAppThread咱们首先来看下这个变量是什么类型
final ApplicationThread mAppThread = new ApplicationThread();
是ApplicationThread,咱们在来看看调用了ActivityManagerService.attachApplication作了什么事情
ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
调用了attachApplicationLocked(),继续看下作了啥
这个方法比较长,我就只取关键的部分贴出来
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
....
try {
...
ProfilerInfo profilerInfo = profileFile == null ? null
: new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
// todo: Yikes! What should we do? For now we will try to
// start another process, but that could easily get us in
// an infinite loop of restarting processes...
Slog.wtf(TAG, "Exception thrown during bind of " + app, e);
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
startProcessLocked(app, "bind fail", processName);
return false;
}
Application是在何时建立的?onCreate()何时调用的?
执行完判断和赋值的操做后最后调用了thread.bindApplication(),刚才看到是ApplicationThread,因此我来看看ApplicationThread.bindApplication
ActivityThread.java
private class ApplicationThread extends ApplicationThreadNative {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
private int mLastProcessState = -1;
...
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
...
}
能够看到是ActivityThread的内部类,我去!你在玩我呢?绕了这么半天又绕回来了。
客官别急,咱们继续向下看,执行bindApplication的时候发了一个消息
sendMessage(H.BIND_APPLICATION, data);
这个H就是咱们前面说的Handler,咱们来看下handler作了哪些处理
private class H extends Handler {
.....
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
看到它调用了handleBindApplication(),其主要做用是绑定个人的自定义的application,作一些初始化操做,咱们继续看
private void handleBindApplication(AppBindData data) {
...
if (ii != null) {
final ApplicationInfo instrApp = new ApplicationInfo();
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
if (mProfiler.profileFile != null && !ii.handleProfiling
&& mProfiler.profileFd == null) {
mProfiler.handlingProfiling = true;
final File file = new File(mProfiler.profileFile);
file.getParentFile().mkdirs();
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
} else {
mInstrumentation = new Instrumentation();
}
....
try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
这里有个比较重要的类,mInstrumentation 为何说它特别重要呢,咱们先来看看它怎么初始化的
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation=(Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();
经过反射建立mInstrumentation 而后给进行一系列初始化操做,而后执行了
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
data.info是一个LoadeApk对象。
LoadeApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
//这里不会执行,觉得传过来的是null,onCreate在上一层执行的
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
}
执行了
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
Instrumentation.java
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
一样经过反射出一个application而且 调用其attach(),也就是说个人自定义application的时候attach就是在这里调用的
接着上面ActivityThread.handleBindApplication()中,首先反射出mInstrumentation
和Application而后执行了下面一句代码
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
调用了mInstrumentation.callApplicationOnCreate(),咱们的Application.oncreate()就是在这里调用的,如今明白为何Instrumentation为何那么重要了吧,它就像个管家婆同样,负责家里的大事小事,可是通常不抛头露面,听一家之主ActivityThread的安排。
好,搞清楚Application后咱们在来看看activity在哪里被初始化以及调用oncreate()方法的
Activity是怎样启动的
前面说了ActivityThread.attach()调用了ActivityManagerService.attachApplication(),在代码中看到经过调用ApplicationThread.bindApplication()绑定了application,咱们在看看bindApplication()以后在干了什么
ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...
try {
...
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
...
}catch (Exception e) {
...
}
...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
调用了mStackSupervisor.attachApplicationLocked(app),mStackSupervisor是ActivityStackSupervisor类型,这个类也是很是重要的,它决定着咱们app是否能启动成功,咱们看看作了什么
ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
//当前应用的整个activity堆信息
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//启动Activity
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
看到调用了realStartActivityLocked(hr, app, true, true)),继续看
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
if (andResume) {
app.hasShownUi = true;
app.pendingUiClean = true;
}
app.forceProcessStateUpTo(mService.mTopProcessState);
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
...
}
看到了调用了app.thread.scheduleLaunchActivity(),这个app是上一层传过来的ActivityRecord,它表明的就是要开启的Activity对象里面分装了不少信息,好比所在的ActivityTask等,若是这是首次打开应用,那么这个Activity会被放到ActivityTask的栈顶,那么这个thread就是咱们的ApplicationThread,咱们回到ActivityThread
看下ApplicationThread.scheduleLaunchActivity()作了什么
ActivityThread.java
private class ApplicationThread extends ApplicationThreadNative {
@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) {
...
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
又用hanlder发了个消息,咱们来看看hanlder怎么处理的
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break;
}
Word天,几经周折又回到ActivityThread本身,心好累。。咱们继续~
ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
//反射建立一个Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//调用Activity.onResume
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out paused, because it
// needs to be visible but isn't in the foreground. We accomplish this by going
// through the normal startup (because activities expect to go through onResume()
// the first time they run, before their window is displayed), and then pausing it.
// However, in this case we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just retain the current
// state it has.
performPauseActivityIfNeeded(r, reason);
// We need to keep around the original state, in case we need to be created again.
// But we only do this for pre-Honeycomb apps, which always save their state when
// pausing, so we can not have them save their state when restarting from a paused
// state. For HC and later, we want to (and can) let the state be saved as the
// normal part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
看到开头 ,关键代码调用了Activity a = performLaunchActivity(r, customIntent);
返回一个Activity,咱们看看performLaunchActivity()
ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//经过反射建立activity实例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
//建立BaseContext
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
//咱们的activity.attach就在这里被调用的
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
咱们看到经过调用mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);返回一个Activity,哇~这个管家婆真是厉害!看看作了啥?确定是反射建立一个Activity嘛。。不信?
Instrumentation.java
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
不得不说Instrumentation真是不辞辛苦啊。。
好,接着上面建立Activity以后,判断activity是否不等于空,走进if里面调用了
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);
原来咱们Activity的attach在这里调用的啊。。。接着下面走
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
看到没!看到没!熟悉不,个人application.onCreate也是这样调用的,管家婆666666
Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
prePerformCreate(activity);
activity.performCreate(icicle);
postPerformCreate(activity);
}
调用了activity.performCreate(icicle);看到这么名字就应该很清楚了吧~,又不信?
Activity.java
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
看到木有~~~回到上面,当执行handleLaunchActivity的时候,调用performLaunchActivity(r, customIntent);返回了Activity以后
咱们接着向下看
ActivityThread.java
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
}
调用了handleResumeActivity,不用说 我敢确定是用mInstrumentation来调用Activity.onResume的,咱们来验证一下
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
....
// TODO Push resumeArgs into the activity for consideration
r = performResumeActivity(token, clearHide, reason);
....
}
继续看performResumeActivity()
public final ActivityClientRecord performResumeActivity(IBinder token,
boolean clearHide, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing resume of " + r
+ " finished=" + r.activity.mFinished);
if (r != null && !r.activity.mFinished) {
if (clearHide) {
r.hideForNow = false;
r.activity.mStartedActivity = false;
}
try {
r.activity.onStateNotSaved();
r.activity.mFragments.noteStateNotSaved();
if (r.pendingIntents != null) {
deliverNewIntents(r, r.pendingIntents);
r.pendingIntents = null;
}
if (r.pendingResults != null) {
deliverResults(r, r.pendingResults);
r.pendingResults = null;
}
r.activity.performResume();
...
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to resume activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
看到了调用r.activity.performResume(),咱们在继续看看Activity.performResume()
Activity.java
final void performResume() {
performRestart();
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onResume()");
}
// invisible activities must be finished before onResume() completes
if (!mVisibleFromClient && !mFinished) {
Log.w(TAG, "An activity without a UI must call finish() before onResume() completes");
if (getApplicationInfo().targetSdkVersion
> android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
throw new IllegalStateException(
"Activity " + mComponent.toShortString() +
" did not call finish() prior to onResume() completing");
}
}
// Now really resume, and install the current status bar and menu.
mCalled = false;
mFragments.dispatchResume();
mFragments.execPendingActions();
onPostResume();
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onPostResume()");
}
}
调用了mInstrumentation.callActivityOnResume(this);看来咱们的验证是没错的
结语
至此,Activity整个的启动流程也讲完了,你们也看到,调用过程极其复杂
源码中各类条件判断让人眼花缭乱,因此说若是你没记住也不要紧,你只要记住这个流程,理解了Android在控制Activity生命周期时是如何操做,以及是经过哪几个关键的类进行操做的就能够了,之后遇到相关的问题之道从哪块下手便可,这些过程我虽然也是撸了一遍,但仍是记不清。
时序图
为了你们方便,我整理了下整个的调用过程
以上是本文讲的整个流程图,写的比较水,但愿对你们学习有所帮助。。。
Android Studio查看源码的小技巧
不知道你们遇到过没,咱们平时作项目的时候,想要查看哪些类使用了这个变量的,或者调用过这个类的方法的时候,都会去按住Ctrl加上鼠标点击那个变量或者方法,可是你只能查看本身的项目使用过
好比你想查看这个方法在哪里使用过你能够按住ctrl再点击这个方法查看它的引用
但是咱们查看源码的时候,好比咱们查看ActivityThread的源码 想看一下handleResumeActivity在哪里调用了,但是你会发现你按住ctrl在点击会找不到引用。为何呢?由于默认是搜索你的项目,也就是说只要你的项目调用了这个方法,你才能够搜到,但是这是系统调用的,我想查看究竟是谁调用的,怎么办捏?
右键单击这个方法弹出菜单,点击Find Usages,快捷是Ctrl+g
默认是搜索咱们的Project引用,咱们修改为
而后点击Find
就找了调用的地方,而后咱们双击就到了调用的那行代码,下次你在按住ctrl单击那个方法的时候就会弹出来引用的地方
这对于咱们查看源码有很大的帮助~