2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 从源码角度看一个apk的启动过程和一个activity的启动过程

从源码角度看一个apk的启动过程和一个activity的启动过程

时间:2022-06-28 17:11:15

相关推荐

从源码角度看一个apk的启动过程和一个activity的启动过程

APK程序的运行过程

首先,ActivityThread从main()函数中开始执行,调用prepareMainLooper()为UI线程创建一个消息队列(MessageQueue)。

public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");SamplingProfilerIntegration.start();// CloseGuard defaults to true and can be quite spammy. We// disable it here, but selectively enable it later (via// StrictMode) on debug builds, but using DropBox, not logs.CloseGuard.setEnabled(false);Environment.initForCurrentUser();// Set the reporter for event logging in libcoreEventLogger.setReporter(new EventLoggingReporter());AndroidKeyStoreProvider.install();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0("<pre-initialized>");Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();//我们在这里发现这个方法 我们看下源码thread.attach(false);if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}}

attach的源码 它便会创建一个Binder线程(具体是指ApplicationThread,Binder的服务端,用于接收系统服务AMS发送来的事件),该Binder线程通过Handler将Message发送给主线程,具体过程可查看 startService流程分析 这里不细说,具体可以了解了解binder机制

private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {ViewRootImpl.addFirstDrawHandler(new Runnable() {@Overridepublic void run() {ensureJitEnabled();}});android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());RuntimeInit.setApplicationObject(mAppThread.asBinder());final IActivityManager mgr = ActivityManagerNative.getDefault();try {mgr.attachApplication(mAppThread);} catch (RemoteException ex) {// Ignore}// 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) {}}}});} 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);}}// add dropbox logging to libcoreDropBox.setReporter(new DropBoxReporter());ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {@Overridepublic void onConfigurationChanged(Configuration newConfig) {synchronized (mResourcesManager) {// We need to apply this change to the resources// immediately, because upon returning the view// hierarchy will be informed about it.if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {// This actually changed the resources! Tell// everyone about it.if (mPendingConfiguration == null ||mPendingConfiguration.isOtherSeqNewer(newConfig)) {mPendingConfiguration = newConfig;sendMessage(H.CONFIGURATION_CHANGED, newConfig);}}}}@Overridepublic void onLowMemory() {}@Overridepublic void onTrimMemory(int level) {}});}

里面发现一个特别重要的类

ViewRootImpl可能大家对它不是很陌生,乍以为他是一个view,熟悉后发现他其实是一个继承于handler的类,这个类是作为native层和view层系统或者说fromwork层通信的桥梁,我们的setcontentview中调用的n多方法,就是在它的消息川底下开始绘制和布局view的 这个ViewRootImpl我们留下去凡汐他,继续回归正题看

然后创建一个ActivityThread对象,在ActivityThread的初始化代码中会创建一个H(Handler)对象和一个ApplicationThread(Binder)对象。其中Binder负责接收远程AmS的IPC调用,接收到调用后,则通过Handler把消息发送到消息队列,UI主线程会异步地从消息队列中取出消息并执行相应操作,比如start、stop、pause等。

我们来看源码

public final class ActivityThread {...final ApplicationThread mAppThread = new ApplicationThread();final Looper mLooper = Looper.myLooper();final H mH = new H();...

接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断地从消息队列中读取并处理消息。

当ActivityThread接收到AmS发送start某个Activity后,就会创建指定的Activity对象。那我们来看看startAvtitity到底干了些什么事

经过几层调用后发现 源码都在Activity.java这个类 都是几个不同参的startactivit互相调用,他们最后都会调用到这里

@Overridepublic void startActivity(Intent intent) {this.startActivity(intent, null);}@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {// Note we want to go through this call for compatibility with// applications that may have overridden the method.startActivityForResult(intent, -1);}}

那么我们来看这个-1的作用 先来看看startActrivityForResult的源码

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {if (mParent == null) {Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);//...此处省略一万行代码2333

这里面一个重要的方法就是

mInstrumentation.execStartActivity(

this, mMainThread.getApplicationThread(), mToken, this,

intent, requestCode, options);

我们来看看他到底搞什么幺蛾子

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, String target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);if (am.match(who, null, intent)) {am.mHits++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess();//重点在这里 ahhhh 那么这个ActivityManagerNative.getDefault()是个什么鬼,我们在下面说int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target, requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}

public abstract class ActivityManagerNative extends Binder implements IActivityManager{/*** Cast a Binder object into an activity manager interface, generating* a proxy if needed.*/static public IActivityManager asInterface(IBinder obj) {if (obj == null) {return null;}IActivityManager in =(IActivityManager)obj.queryLocalInterface(descriptor);if (in != null) {return in;}return new ActivityManagerProxy(obj);}/*** Retrieve the system's default/global activity manager.*/static public IActivityManager getDefault() {return gDefault.get();}

我们发现getdefault会返回一个IActivityManager对象

其实这个返回的是ActivityManagerProxy的实例,它只是一个代理类,这个代理类实际上代理的是IBinder b = ServiceManager.getService("activity")这个Service。public interface IActivityManager extends IInterface {public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,ProfilerInfo profilerInfo, Bundle options) throws RemoteException;

注册的系统服务 我们发现实现的这个IInterface会回调一个IBinder类型的变量,说明系统内部通信实际上也是使用的binder机制 那么初始化或者说注册这个AMS后要怎么呢 我们来看看看看大概流程,到最后instrumention ->new activity()初始化activity,初始化conteximpl 通过activity的attache方法回调onCreate() oncreate方法调用setContentView addView和初始化decorView和各种ViewGroup和View同时activityThread handleResumeActivity 调用acytivity的onresume使用profomeMersure和profomeDraw完成界面绘制;

大概绘制流程是这样 我们在下篇博客讲

Activity又会创建PhoneWindow类→DecorView类→创建相应的View或者ViewGroup。创建完成后,Activity需要把创建好的界面显示到屏幕上,于是调用WindowManager类,后者于是创建一个ViewRoot对象,该对象实际上创建了ViewRoot类和W类,创建ViewRoot对象后,WindowManager再调用WmS提供的远程接口完成添加一个窗口并显示到屏幕上。

接下来,用户开始在程序界面上操作。KeyQ线程不断把用户消息存储到QueueEvent队列中,InputDispatcherThread线程逐个取出消息,然后调用WmS中的相应函数处理该消息。当WmS发现该消息属于客户端某个窗口时,就会调用相应窗口的W接口。

W类是一个Binder,负责接收WmS的IPC调用,并把调用消息传递给ViewRoot,ViewRoot再把消息传递给UI主线程ActivityThread,ActivityThread解析该消息并做相应的处理。在客户端程序中,首先处理消息的是DecorView,如果DecorView不想处理某个消息,则可以将该消息传递给其内部包含的子View或者ViewGroup,如果还没有处理,则传递给PhoneWindow,最后再传递给Activity。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。