在Android的四大组件之中相信最常用的就是Activity,相信每一个App或多或少都要有Activity的存在,几乎所有用户的交互方式都是通过Activity进行的,因此Activity类需要创建窗口通过setContentView方法来显示界面。当然现在的大屏设备以及更加复杂的用户界面也需要应用到Fragment这种片段类的方式来参与构建,但是作为今天的主角我们要从多方面的角度来分析Activity这个重要的组件。
Activity的生命周期
在系统活动中Activity被一种activity stack(栈)管理着,当一个新的Activity启动时,它被放置在堆栈的顶部成为活动的Activity,之前的Activity会始终保持位于新的Activity堆栈之下,而不会再次到达前台,直到新的Activity退出前台。Activity一般存在四种状态
四种状态
- 活动状态
如果Activity是在屏幕最前端显示(在堆栈的顶部)时,它是活动的或称之为运行的。 - 暂停状态
如果Activity已失去焦点,但仍清晰可见(即一个新的非全尺寸或透明的Activity或dialog集中在你的Activity上面)则暂停。一个暂停的Activity是完全活着(它保持所有的状态和信息,并保持连接在窗口管理器window manager上),但是在系统极端低内存的情况下会被杀死。 - 隐藏状态
如果Activity完全被另一个Activity遮蔽,那它就停止了。它仍然保留所有的状态和成员信息,但是它不再对用户可见,所以它的窗口是隐藏的,它有时会因系统其他地方需要内存而被杀死。 - 停止状态
如果Activity暂停或停止,系统可以通过finish方式将其从内存中清除,或者干脆杀死它的进程。当Activity重新启动时,它必须重新按照流程启动恢复到原来的状态。
让我们来关注一下Activity的生命周期,这样更容易理解以上所说的四种状态,Activity生命周期可以分为正常的生命周期(用户参与情况下)和异常的生命周期(系统回收或者当前设备的Configuration发生改变导致Activity销毁重建),两种情况会有所不同。
生命周期
以下是Google官方文档提供的生命周期图
我们可以在三个关键期间做一些文章
- 由onCreate创建并最终由onDestroy销毁期间,Activity的onCreate方法具有“全局性”的设置,比如开启一个新的线程,相应的可以在onDestroy中停止这些启动的线程,来完结整个生命周期。
- 由onStart开启直到相应onStop结束期间,此时Activity已经形成,但是还看不见,这里我们可以做相应的UI处理,比如注册一个广播onStart中来监控操作,然后改动UI变化,然后在onStop中销毁这个广播。
- 由onResume到相应onPause期间短暂的时间里,重视的是用户和界面之间的交互代表着Activity已经位于前台,这一期间会频繁发生,如新的Intent传递,设备进入睡眠状态等,所以这里的代码要比较轻巧。
然后我们来说一下生命周期
1. 正常情况下的生命周期
onCreate:表示Activity正在被创建,这个方法中,我们可以做一些全局初始化工作,入setContentView,初始化Activity所需要的数据等。
onStart:表示Activity正在启动,即将开始,这是Activity已可见,但是还没出现在前台,无法交互,我们还看不见。
onResume:表示Activity已经可见了,已在前台开始活动了,onResume重要的标志是Activity位于了前台(用户已可见)。
onPause:这个部分很重要,表示Activity正在停止,紧接着onStop就会调用,这里可以做一些存贮数据(数据持久化)停止动画等工作,注意不要太耗时,会影响到新的Activity的显示,因为onPause需要先执行,新Activity的onResume才能执行,这点要注意一下。
onStop:表示Activity即将停止,可以做一些稍微多一些的回收工作,同样不要太耗时。另如果当前Activity采用透明主题,切换Activity或点击Home键时不会回到此方法。
onDestroy:这里代表销毁Activity,做一些最终资源的释放,这一步骤的发生往往是人为做了finish处理或因为系统为了节约空间暂时性销毁,可以通过isFinish方法区别这两种情况。
onRestart:表示Activity重新启动,由隐藏变为活动状态(见上面四种状态)时所回调的方法,比如用户点击Home键或打开新的Activity造成onStop执行,然后回到这个界面产生的回调。
2. 异常情况下的生命周期
Activity可能会由于内存资源不足或者系统配置发生变化导致Activity被杀死并重新创建,因为一旦配置改变,则任何显示用户界面将需要更新以匹配新的配置,比如旋转屏幕方向等。 但是在这个过程中,系统会调用onSaveInstanceState来保存当前Activity的状态,注意这个方法调用时机是在onStop之前和onPause没有既定的顺序。这个回调只会发生在异常的生命周期情况下,再重新创建后系统会调用onRestoreInstanceState将之前保存到Bundle信息传给RestoreInstanceState和onCreate方法,因此,我们可以通过onRestoreInstanceState和onCreate方法来判断Activity是否被重建了,onRestoreInstanceState会在onStart之后执行。
对于数据恢复这部分,系统的View也帮我们做了一些工作,每个View也有自己的onSaveInstanceState和onRestoreInstanceState这两个方法。
下面我们做一个例子,用转动屏幕的方式来看一下View的数据存贮恢复和我们自己的数据存贮恢复情况:
public class MainActivity extends ActionBarActivity {
private final static String TAG = "myTag";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
Log.d(TAG, "oncreate:" + savedInstanceState.getString("data"));
}
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
Log.d(TAG, "onSaveInstanceState");
outState.putString("data", "test_entity");
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.d(TAG, "onRestoreInstanceState:" + savedInstanceState.getString("data"));
}
}
这两种接收方式都可以,官方推荐使用onRestoreInstanceState方法,他们的区别在于onCreate方法中无法自行鉴别Bundle是否有值需要判断,而onRestoreInstanceState不用。我们可以看一下方法执行的效果。
看以看到我们输入的文字在经过屏幕变化后还是显示的,我们的Log信息也有显示,可见,Android系统的View和我们对数据的恢复都起了作用。
当Android资源内存资源内存不足时也会导致低优先级的Activity被杀死,状态越靠前优先级越高(见前面Android四种状态)。同样系统同样会后续通过onSaveInstanceState和onRestoreInstanceState来存贮和恢复数据,如果一个进程没有四大组件在执行,那么这个进程将很快被系统杀死,因此一些后台工作要依赖四大组件运行,可以用Service保证优先级,关于Service 我们会后期分析。当然我们可以可以人为的控制系统配置,让其不进行重新创建。就是指定configChanges属性,比如禁止旋转屏幕且隐藏键盘
android:configChanges=”orientation|keyboardHidden”;
这样就可以了,因为configChanges属性变化就会导致Activity重新创建,所以我们可以人为控制:
配置后代码类似下面这样:
<activity
android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Activity的启动模式
接下来我们来说一下Activity的启动模式,Activity默认启动后会放在activity stack的顶部,多次创建同一个Activity会产生多个对象,当我们点击back键时,会发现有多个同一个Activity的效果。有些时候这并不是我们想要到效果。那么我们就要通过Activity的启动模式来控制Activity的启动方式,如何使用呢只需要配置launchMode就好
<activity
android:name=".SingleTaskActivity"
android:label="singleTask launchMode"
android:launchMode="singleTask|standard|singTop|singleInstance">
</activity>
或者通过Intent设置,比如:
Intent intent = new Intent();
intent.setClass(MainActivity.this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
优先级通过Intent设置要高于清单文件中,Intent方式无法设定一种模式,而是一种启动方式,让我们来看一下这些常用的标记位Flags:
FLAG_ACTIVITY_SINGLE_TOP
和Activity的Launch mode的singleTop类似。如果某个intent添加了这个标志,并且这个intent的目标activity就是栈顶的activity,那么将不会新建一个实例压入栈中,如果目标activity已在栈顶则不出创建新的activity。FLAG_ACTIVITY_CLEAR_TOP
例如现在的栈情况为:A B C D 。D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP标记,则栈情况变为:A B。如果没有添加这个标记,则栈情况将会变成:A B C D B。这跟上面把B的Launch mode设置成singleTask类似。简而言之,跳转到的activity若已在栈中存在,则将其上的activity都销掉。FLAG_ACTIVITY_NEW_TASK
例如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在Manifest.xml的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。如果D的Task affinity默认没有设置,则会把其压入栈1,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK标记效果是一样的了。效果和“singleTask”相同。FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果设置,新的Activity不会在最近启动的Activity的列表中保存。等同于在xml实现android:excludeFromRecents=”true”。
standard模式
标准模式,也是系统默认的模式,每次启动都会生成一个Activity对象,在这种模式下,谁启动了这个Activity那么这个Activity就会运行在启动这个Activity所在的栈中。当我们用ApplicationContext启动standard模式的Activity时会报错,因为非Activity的context没有任务栈就有了这种问题,可以采用其他模式启动。
singleTop模式
栈顶复用模式,如果Activity已经位于栈顶,就不会在为我们创建新的Activity,同时会回调onNewIntent方法,如果Activity存在但是不是位于栈顶,那么还是会创建的。只有在调用者和目标Activity在同一Task中,并且目标Activity位于栈顶,才会使用现有目标Activity实例,否则创建新的目标Activity实例。singleTop的应用场景很多,关于singleTop一个典型的使用场景就是搜索功能。假设有一个搜索框,每次搜索查询都会将我们引导至SearchActivity查看结果,为了更好的交互体验,我们在结果页顶部也放置这样的搜索框。假设一下,SearchActivity启动模式为standard,那么每一个搜索都会创建一个新的SearchActivity实例,10次查询就是10个Activity。当我们想要退回到非SearchActivity,我们需要按返回键10次,这显然太不合理了。
singleTask模式
栈内复用模式,只要在栈中存在这个Activity多次启动是不会再创建这个实例的,系统也会回调onNewIntent方法。当一个具有singleTask模式的Activity请求启动时,系统会寻找是否有Activity需要的任务栈,如果不存在就创建一个Activity所需的任务栈,然后把其放在栈中。如果存在这个任务栈,要看栈中是否有这个Activity,如果有,系统就会调用onNewIntent方法,把Activity调回栈顶并采用cleanTop方式,将Activity上的其他Activity全部出栈,如果没有则会创建一个实例压入栈中。同时我们也要谨慎使用这种模式,因为它可以在用户未感知的情况下销毁掉其他Activity。其实所需要的任务栈是通过TaskAffinity的参数指定的,默认情况下所有Activity所需要的任务栈名字和应用包名相同,TaskAffinity属性主要和singleTask启动模式和allowTaskReparenting属性配对使用,其他情况下没有意义,任务栈分为前台栈和后台栈,后台栈可以通过切换的方式调到前台。
singleInstance模式
单实例模式,是一种加强版的singTask模式,除了具有singleTask所有特性外,还加强了一点,那就是具有这种模式的Activity只能单独位于一个任务栈中。如果从singleInstance Activity实例启动另一个Activity,那么这个Activity实例会放入其他的Task中。同理,如果singleInstance Activity被别的Activity启动,它也会放入不同于调用者的Task中。由于栈内复用的特性,后续的请求不会创建新的Activity。
IntentFilter的匹配规则
下面我们来说一下Intent在Activity的匹配规则,Android中启动Activity分为显示和隐示两种方式,原则上Intent不会既是显示又是隐示,如果出现以显示为准。显示调用通过startActivity就可以进行,隐示调用一般更加灵活,下面我们来看一下通过Activity中的IntentFilter过滤信息设置来进行隐式调用。过滤信息包含着action、category和data。一个Activity可以含有多个intent-filter,一个Intent只要匹配一个intent-filter就可以成功的找到对应的Activity,下面我们详细说一下每一个过滤信息。
action
一个过滤中可以有多个action,同时我们也可以在应用中定义自己的action,如果Intent中没有指定action那么匹配会失败,所以intent中至少有1个action,而且intent中不能包含过滤中没有的action,还要注意action中大小写是有区分的。
匹配规则:action的匹配,要求是Intent中至少含有一个action,且这一个或多个action能在过滤规则中找到相同的action
category
category和action不同,在Intent中可以没有category(系统会默认添加),如果含有category那么所有的category必须和过滤规则中的其中一个category相同,其实系统在调用startActivity和startActivityForResult时候会默认为Intent加上”android.intent.category.DEFAULT”这个category。注意,如果你想隐式启动某个组件,那么就得在IntentFilter中添加”android.intent.category.DEFAULT”这个category才行,因为系统会默认给Intent设置default标签的。
匹配规则:category要求Intent中可以没有category(其实是系统已经默认添加),但是你一旦有category,不管几个,每个都要和IntentFilter中的category相同
data
data由mimeType和URI组成,mimeType代表媒体类型,比如audio、jpeg可以表示图片、文本、视频等不同的媒体格式。URI指资源地址,结构如下:
< scheme >: // < host >:< port >/ [< path > | < pathPattern >]
scheme:访问资源的命名机制,比如http、content等,没有模式整个URI无效。
host+post:存放资源的主机名和端口号。
path | pathPatern:资源自身的名称,由路径表示,其中pathPatern表示带有通配符。
data的匹配方式和action类似,如果过滤条件中有data那么intent中也要有且能匹配过滤条件中的数据,data中是要能够完全匹配,即intent中的data部分也出现在了过滤条件中
注意!如果intent-filter中是:
< data android:mimeType=”image/*” />
那么指定为图片类型,这种情况下虽然没有指定URI,但是却有默认值,是content和file。也就是说,虽然没有URI但是intent的URI部分的schema必须为content或者是file才能匹配。 还有如果为Intent指定完整的data,必须调用setDataAndType方法,先后调用setData和setType会造成彼此消除对方,从源码中可以看出来。
匹配规则:如果IntentFilter中有定义data,那么Intent中也必须至少含有其中的一个data信息与data是匹配的
下面我们举一个相互匹配的例子来看看intentFilter如何使用(如果不匹配的话跳转会发生crash,抛出异常):
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="com.my.data" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.my.category1" />
<category android:name="com.my.category2" />
<data
android:scheme="http"
android:host="hkx"
android:port="11"
android:path="/abc"
android:mimeType="video/*"/>
<data
android:path="/dd/b"
android:scheme="content" />
<data android:mimeType="image/*" />
</intent-filter>
相匹配的intent设置方式如下:
Intent intent = new Intent();
intent.setAction("com.my.data");//至少有一个,且只要能匹配到过滤中的一个
// intent.setAction("android.intent.action.SEND");//可以不囊括过滤中所有的action
// intent.setAction("com.my.nodata");//不能含有过滤中没有的action
intent.addCategory("android.intent.category.DEFAULT");//这个是默认的categroy可以不写(不写也会有)
intent.addCategory("com.my.category1");//过滤规则中必须有这个category
// intent.addCategory("com.my.category2");//可以不全囊括过滤中所有的category
// intent.addCategory("com.my.noategory");//不能含有过滤中没有的category
intent.setDataAndType(Uri.parse("http://hkx:11/abc"), "video/*");//是过滤中的信息
intent.setDataAndType(Uri.parse("http://hkx:11/cba"), "image/*");//是过滤中的信息
intent.setDataAndType(Uri.parse("http://hkx:11/abc"), "image/*");//是过滤中的信息 这样写也可以对比上面
intent.setDataAndType(Uri.parse("http://hkx:11/cba"), "video/*");//是过滤中的信息 这样写也可以对比上面
startActivity(intent);
最后我们说明一下:有一类action和category非常重要:
< action android:name=”android.intent.action.MAIN” />
< category android:name=”android.intent.category.LAUNCHER” />
这两个表示了这是一个入口Activity并且会出现在系统列表中,两个中少了任何一个都没有意义,Service、BroadCastReceiver也有这些类似方法去获取匹配信息。
Activity的工作过程
在调用方式上来说,Activity和Service与BroadCastReceiver一样都需要Intent,由于系统对Activity的启动流程已经帮助我们进行了封装,所以我们一般不是很关注这一点,我们只需要调用startActivity就可以启动一个Activity,那么系统对Activity启动是如何实现的呢,这个Activity的底层是如何实现的呢?下面我们来简单探讨一下
我们看一下startActivity这个启动的方法
public void startActivityForResult(Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
@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);
}
}
可以看到最它们都调用了startActivityForResult方法。那么下面我们看一看这个方法又是什么
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
// 这里的mParent是ActivityGroup,已被废弃,所以一般activity这个值为空
if (mParent == null) {
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);
}
}
if (options != null && !isTopOfTask()) {
mActivityTransitionState.startExitOutTransition(this, options);
}
}
我们可以看到mInstrumentation.execStartActivity方法是启动这个activity的真正方法。我们再来看一下这个启动过程
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//核心功能在这个whoThread中完成,其内部scheduleLaunchActivity方法用于完成activity的打开
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
//先查找一遍看是否存在这个activity
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++;
//如果目标activity无法打开,直接return
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
//这里才是真正打开activity的地方,核心功能在whoThread中完成。
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
//这个方法是专门抛异常的,它会对结果进行检查,如果无法打开activity,
//则抛出诸如ActivityNotFoundException类似的各种异常
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
接下来我们要去看下IApplicationThread,因为核心功能由其内部的scheduleLaunchActivity方法来完成
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
构造一个activity记录,然后发送一个消息,所以,我们要看看Handler是如何处理这个消息的,现在转到这个Handler,它有个很短的名字叫做H
private class H extends Handler {
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
//这里处理LAUNCH_ACTIVITY消息类型
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//这里处理startActivity消息
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
下面看最后一个方法,这个方法是activity的启动过程的真正实现。
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);
}
//首先从intent中解析出目标activity的启动参数
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();
//用ClassLoader(类加载器)将目标activity的类通过类名加载进来并调用newInstance来实例化一个对象
//其实就是通过Activity的无参构造方法来new一个对象,对象就是在这里new出来的。
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
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) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
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;
//目标activity的onCreate被调用了,到此为止,Activity被启动了,接下来的流程就是Activity的生命周期了,
//本文之前已经提到,其生命周期的各种状态的切换由ApplicationThread内部来完成
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.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
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;
}
ok,我们简单的分析了一下流程,由于系统其实对Activity启动处理比较复杂,如果深入研究还需要多涉猎一些资料。
说了这么多,我们对Activity的分析就暂且说到这里,可能不是很详细,希望对读者和自己日后有一些帮助吧 ~