Activity启动流程笔记(一)
来源:互联网 发布:centos防火墙关闭端口 编辑:程序博客网 时间:2024/05/21 00:15
从startActivity开始说起:
public void startActivity(Intent intent, 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); } }
进入startActivityForResult看看:
/** * Launch an activity for which you would like a result when it finished. * When this activity exits, your * onActivityResult() method will be called with the given requestCode. * Using a negative requestCode is the same as calling * {@link #startActivity} (the activity is not launched as a sub-activity). * * <p>Note that this method should only be used with Intent protocols * that are defined to return a result. In other protocols (such as * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may * not get the result when you expect. For example, if the activity you * are launching uses the singleTask launch mode, it will not run in your * task and thus you will immediately receive a cancel result. * * <p>As a special case, if you call startActivityForResult() with a requestCode * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your * activity, then your window will not be displayed until a result is * returned back from the started activity. This is to avoid visible * flickering when redirecting to another activity. * * <p>This method throws {@link android.content.ActivityNotFoundException} * if there was no Activity found to run the given Intent. * * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * @param options Additional options for how the Activity should be started. * See {@link android.content.Context#startActivity(Intent, Bundle) * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * * @see #startActivity */ public void startActivityForResult(Intent intent, int requestCode, Bundle options) { if (mParent == null) {/*1*/ Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } final View decor = mWindow != null ? mWindow.peekDecorView() : null; if (decor != null) { decor.cancelPendingInputEvents(); } // TODO Consider clearing/flushing other event sources and events for child windows. } else { if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }
mParent 表示Activity的父Activity,在用ActivityGroup的时候会出现这种情况,现在几乎不会用到,所以直接看mParent != null这种情况。在进入mInstrumentation的execStartActivity方法之前先看看参数:mMainThread.getApplicationThread()返回一个AplicationThread对象,这个对象其实是一个Binder,用于AMS与Activity通信。mMainThread是ActivityThread,ActivityThread是一个app的入口,mToken是一个AppWindowToken类型的对象,专门标识Activity类型的Window。
来看下Instrumentation的execStartActivity:
public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity 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(); int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; }
主要看这段代码:ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
这个方法参数有点多,先看ActivityManagerNative.getDefault这个函数,他其实返回了一个AMS在客户端的代理,即一个ActivityManagerProxy
static public IActivityManager getDefault() { return gDefault.get(); }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; } };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); }
可以得知之前的startActivity调用的是ActivityManagerProxy中的方法
看到ActivityManagerProxy与ActivityManagerService都继承自ActivityManagerNative,可以想到AIDL,启动Activity需要通过AIDL跨进程与AMS交互,所以在ActivityManagerProxy的startActivity会将AIDL需要的参数进行快进程传递
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(caller != null ? caller.asBinder() : null); data.writeString(callingPackage); intent.writeToParcel(data, 0); data.writeString(resolvedType); data.writeStrongBinder(resultTo); data.writeString(resultWho); data.writeInt(requestCode); data.writeInt(startFlags); data.writeString(profileFile); if (profileFd != null) { data.writeInt(1); profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } if (options != null) { data.writeInt(1); options.writeToParcel(data, 0); } else { data.writeInt(0); } mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); reply.readException(); int result = reply.readInt(); reply.recycle(); data.recycle(); return result; }
可以看到IApplicaiotnThread对象也被包装成一个binder传递到AMS端,传递的实际是个ApplicationThreadProxy类型,用于AMS向ActivityThread通信,控制Activity。
至此,就进入到AMS中进行后续的启动。
- Activity启动流程笔记(一)
- Activity启动流程笔记(二)
- Android Activity(一)启动流程
- Activity启动流程源码分析之入门(一)
- app( activity) 启动流程
- 深入理解Activity启动流程(一)–Activity启动的概要流程
- 深入理解Activity启动流程(一)–Activity启动的概要流程
- 深入理解Activity启动流程(一)–Activity启动的概要流程
- 插件占坑,四大组件动态注册前奏(一) 系统Activity的启动流程
- Android系统应用框架篇:Activity启动流程(一)
- Activity的启动流程(二)
- Activity的启动流程(二)
- Activity启动流程源码解析(原创)
- Activity启动流程分析(二)
- Activity启动过程(一)
- Activity的启动流程
- activity 启动流程分析
- Activity启动流程
- Angular 2 中的组件(一)
- javascript实现-简易计算器
- 小米2S ROM重分区
- [Boolan] C++第三周学习笔记
- c# 解决 EntityFramework 基础提供程序在 Open 上失败
- Activity启动流程笔记(一)
- 初识Java虚拟机(10)动态分派的实现
- 数字基带传输与码间干扰
- 共同学习Java源代码-数据结构-TreeSet(二)
- poj_3254 Corn Fields(状压dp)
- 设计模式总论
- Qt一些宏的用法
- 关于Windows系统中一些实用的修改常识
- 线性规划与网络流24——航空路线问题