Activity启动源码解析

[TOC]

Activity

Activity的启动过程

sequenceDiagram
    ActivityThread->>ActivityThread:main()init application
    ActivityThread->>ActivityThread:attach() 
    ActivityManagerNative->>ActivityManagerNative:getDefault
    ActivityManagerNative->>ActivityManagerProxy:attachApplication
    ActivityThread->>ActivityThread:handleLaunchActivity()
    ActivityThread->>ActivityThread:performLaunchActivity(r, customIntent)
  • main()方法里面有个主要做了创建ActivityThread还有创建application的操作
1
2
final IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread)
  • 在attach里面 创建了ActivityManagerNative是一个单例,继承于Bundle,实现了IActivityManager,其实和native交互的方法接口
  • 单例获取的是一个代理类ActivityManagerProxy,其实ActivityManagerNative的一个内部类,那么是怎么创建的呢?拿单例的时候
    先从service中拿到了activity的服务然后传递个asinterface
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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;
    }
    };

再通过asinterface创建

1
2
3
4
5
6
7
8
9
10
11
12
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);
}

获取这个IBinder实例是为了和ActivityManager进行通讯,

1
IBinder b = ServiceManager.getService("activity");

再来看

1
2
3
4
5
public void attachApplication(IApplicationThread app){
...
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
...
}

这里讲这个IApplicationThread传递给 并且通过tracsact传递给ActivityManager
回到

1
2
final IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread)

这里面mAppThread是什么呢?是ActivityThread的一个内部类

1
private class ApplicationThread extends ApplicationThreadNative {

那么ApplicationThreadNative呢?

1
2
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {

留意一下这个参数

1
2
3
4
5
6
public interface IApplicationThread extends IInterface {
...
String descriptor = "android.app.IApplicationThread";
//留意下这个参数
...
}

那么接着走attachApplication

1
2
3
4
5
6
7
private final boolean attachApplicationLocked(IApplicationThread thread
, int pid) {
...
thread.bindApplication();
//注意啦!
...
}

然后和之前一样transact方法

1
2
3
4
5
6
7
8
9
10
11
12
public final void bindApplication(String packageName, ApplicationInfo info,
List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
Bundle testArgs, IInstrumentationWatcher testWatcher,
IUiAutomationConnection uiAutomationConnection, int debugMode,
boolean openGlTrace, boolean restrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) throws RemoteException {

mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}

这时候调用到了ApplicationThread里面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle 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.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}

由于ApplicationThread是ActivityThread的内部类,这里的消息发送到了ActivityThread
然后在handler里面看到以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void handleBindApplication(AppBindData data) {
...
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName())
.newInstance();
//通过反射初始化一个Instrumentation仪表。后面会介绍。
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
//通过LoadedApp命令创建Application实例
mInitialApplication = app;
...
mInstrumentation.callApplicationOnCreate(app);
//让仪器调用Application的onCreate()方法
...
}

这里创建了mInstrumentation

  • performLaunchActivity 利用 Instrumentation.newActivity()利用classloader创建了一个activity并且执行attach方法将token传入,并且在里面初始化了window,设置activity的windowManager

    window的实现是phoneWindow 里面有两个东西一个是DocView FrameLayout,一个是 mContentParent ViewGroup
    setContentView里面的installDocer()方法里面有
    mContentParent = generateLayout(mDecor);这样一句话就很明亮了

sequenceDiagram

    Launcher(Activity)->>Activity:点击屏幕,startActivitySafely()
    Launcher(Activity)->>Activity:startActivity
    Activity->>Instrumentation:startActivityForResult
    Instrumentation->>ActivityManagerProxy:execStartActivity
    ActivityManagerProxy->>ActivityManagerService:startActivity
*从ActivityLauncher启动 > Launcher.onClick(View v)单击app图标 > Launcher.startActivitySafely(v, intent, tag)这里比4.0多的一个参数,可能性能优化吧 > Launcher.startActivity(v, intent, tag) > Activity.startActivity(intent, opts.toBundle()) > Activity.startActivityForResult(intent, -1, options); 不管是在桌面启动还是一个app启动另一个app都是由ActivityManager管理的,他们则要用到Binder activity在启动的过程就是执行startActivityForResult() 那么startActivityForResult执行了Instrumentation的 executeStartActiivty方法
1
2
3
4
5
6
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);
然后ActivityMonitor会将这一消息分发到ActivityManager * 这里有两个重要的东西一个是mMainThread.getApplicationThread() 其实就是一个Bundler因为ApplicationThread继承ApplicationThreadNative,其相当于Stub,ApplicationThreadProxy相当于proxy * 还有一个东西是token,在activity attach的时候传入,也就是Activity创建与关联的时候,也是个Bundle对象,它代表Launcher这个Activity,也就是通过Instrumentation传给ActivityServiceManager * 然后instrumentation这个对象再通过ActivityManagerNative.GetDefault()的startactivity方法来完成相应的对象创建 > 此处省略bundle的机制 > 由此可知Activity是由activityManagerNative.getDefault() > 以上处是启动activity后调用Native的过程
sequenceDiagram
    ActivityManagerService->>ActivityManagerService:startActivityMayWait
    ActivityManagerService->>ActivityManagerService:startActivityLocked
    ActivityManagerService->>ActivityManagerService:startActivityUncheckedLocked:1675
    ActivityManagerService->>ActivityStack:ActivityManagerService:2074
    ActivityStack->>ActivityStack:resumeTopActivitiesLocked
sequenceDiagram
    Launcher->>ActivityManagerService:启动Activity传递thread和activity
    ActivityManagerService->>Launcher:记录信息通知进入pause状态
    Launcher->>ActivityManagerService:暂停后,告诉你可以启动新的activity了
    ActivityManagerService->>新app:启动进程,创建thread并attach传递
    新app->>ActivityManagerService:启动后将thread传递给AMS
    ActivityManagerService->>新app:绑定application,启动Activity

那么可以知道启动过程是

启动app先通过ActiivtyManagerService,ActivityManagerService记录信息,并将原来的app进入pause状态,先pause然后启动想要启动的app,

1
graphy

Activity的四种启动模式

Activity的四种启动模式是什么?

Standard
  • Activit的模式启动模式大部分情况下都使用这种模式
SingleTop
  • 如果SingleTop已经位于栈顶,就不去创建新的Activity
  • 如果SingleTop不位于栈顶,则创建新的Activity
  • 系统不会调用Oncreate,而是走OnNewIntent()方法

    比如一个搜索页面,可以产生搜索内容和结果,则不会用户每次搜索都产生一个实例.

    SingleTask
  • 位于栈顶则和SingleTop一样
  • 不在栈顶的时候,把Activity移动到栈顶,并执行OnNewIntent方法
  • 在Activity栈内,其实单例
    SingleInstance
  • 启动一个新的Activity栈,并将Activity移动新的栈内
  • 不同Activity栈切换的话,Activity切换动画会不流畅
  • 重复创建SingleInstance的话,只会存在一个
  • 在不是SingleInatance的栈内,点击返回,则会返回这个栈内所有的Activity,然后才会回到SingleInstance
  • 动态设置Activity的启动模式

affinity

  • 默认是app的包名
  • 在application可以设置
  • activity和application都有这个属性

    1
    2
    3

    <application
    android:taskAffinity="gf.zy"
  • Intent.FLAG_ACTIVITY_NEW_TASK

    意思是创建一个新的栈,举了一个例子,oneapp启动twoapp两个app如果没有用FLAG_ACTIVITY_NEW_TASK,则按home是一个app如果用了FLAG_ACTIVITY_NEW_TASK,则是两个app

  • Intent.FLAG_ACTIVITY_SINGLE_TOP
    和SingleTop相同

  • Intent.FLAG_ACTIVITY_CLEAR_TOP

    Activity的栈

    任务栈(Task Stack) 回退栈(Back Stack)

  • Activity在创建初期都会默认的分配一个任务栈
  • 一个TaskStack只要不在栈顶,就是Stop状态
  • 任务栈的Id是自增长的,Integer类型
谢谢您的鼓励~