从源码角度看一个apk的启动过程和一个activity的启动过程
2016-05-06 16:19
344 查看
APK程序的运行过程
首先,ActivityThread从main()函数中开始执行,调用prepareMainLooper()为UI线程创建一个消息队列(MessageQueue)。
attach的源码 它便会创建一个Binder线程(具体是指ApplicationThread,Binder的服务端,用于接收系统服务AMS发送来的事件),该Binder线程通过Handler将Message发送给主线程,具体过程可查看 startService流程分析 这里不细说,具体可以了解了解binder机制
里面发现一个特别重要的类
ViewRootImpl可能大家对它不是很陌生,乍以为他是一个view,熟悉后发现他其实是一个继承于handler的类,这个类是作为native层和view层系统或者说fromwork层通信的桥梁,我们的setcontentview中调用的n多方法,就是在它的消息川底下开始绘制和布局view的 这个ViewRootImpl我们留下去凡汐他,继续回归正题看
然后创建一个ActivityThread对象,在ActivityThread的初始化代码中会创建一个H(Handler)对象和一个ApplicationThread(Binder)对象。其中Binder负责接收远程AmS的IPC调用,接收到调用后,则通过Handler把消息发送到消息队列,UI主线程会异步地从消息队列中取出消息并执行相应操作,比如start、stop、pause等。
我们来看源码
接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断地从消息队列中读取并处理消息。
当ActivityThread接收到AmS发送start某个Activity后,就会创建指定的Activity对象。那我们来看看startAvtitity到底干了些什么事
经过几层调用后发现 源码都在Activity.java这个类 都是几个不同参的startactivit互相调用,他们最后都会调用到这里
那么我们来看这个-1的作用 先来看看startActrivityForResult的源码
这里面一个重要的方法就是
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
我们来看看他到底搞什么幺蛾子
我们发现getdefault会返回一个IActivityManager对象
注册的系统服务 我们发现实现的这个IInterface会回调一个IBinder类型的变量,说明系统内部通信实际上也是使用的binder机制 那么初始化或者说注册这个AMS后要怎么呢 我们来看看看看大概流程,到最后instrumention ->new activity()初始化activity,初始化conteximpl 通过activity的attache方法回调onCreate() oncreate方法调用setContentView addView和初始化decorView和各种ViewGroup和View同时activityThread handleResumeActivity 调用acytivity的onresume使用profomeMersure和profomeDraw完成界面绘制;
![](http://img.blog.csdn.net/20160509145349212)
大概绘制流程是这样 我们在下篇博客讲
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。
首先,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 libcore EventLogger.setReporter(new EventLoggingReporter()); AndroidKeyStoreProvider.install(); // Make sure TrustedCertificateStore looks in the right place for CA certificates final 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(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"); } }
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() { @Override public 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 libcore DropBox.setReporter(new DropBoxReporter()); ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public 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); } } } } @Override public void onLowMemory() { } @Override public 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互相调用,他们最后都会调用到这里
@Override public void startActivity(Intent intent) { this.startActivity(intent, null); } @Override public 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。
相关文章推荐
- Android ViewPager滑动事件讲解
- 使用SharedApplication进行传值
- c# windows服务如何获取自己的安装路径
- 如何设计和维护好一个大项目
- 安卓面试题
- 【Shell】一些比较有用、常用的shell命令
- Python全栈开发之3、数据类型set补充、深浅拷贝与函数
- django 获取系统当前时间 和linux 系统当前时间不一致 问题处理。
- IOS UITextField输入位数限制
- canvas 二 canvas绘制表盘,及canvas曲线的绘制
- android GridView显示相同尺寸图片以及预览功能
- python学习2016.4.13
- javascript查找DOM元素的方法总结
- OpenFileDialog获取文件名和文件路径问题
- [No00008C]图解SQL的各种连接join让你对SQL的连接一目了然
- 湖南纪委通报7名党员干部处理
- 超级表格全新升级,这些功能你不可能在其他软件上看到
- python基础IV(切片、迭代、生成列表)
- 织梦根目录下面404页面,主页能正常运行404页面,切换至栏目页404页面内的图片不能正常显示,解决方案
- 对象适配器模式学习