新手.activity启动器新手入门怎么玩股票

匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。  在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作。在Android中Activity的启动模式决定了Activity的启动运行方式。
Activity启动模式设置:&activity android:name=".MainActivity" android:launchMode="standard" /&
Android总Activity的启动模式分为四种:
Activity的四种启动模式:
1. standard
模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。
2. singleTop
如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
3. singleTask
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
4. singleInstance
在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。
1、standard是系统默认的启动模式。
Standard模式是每次都会创建新的Activity对象,当点击返回按钮时,他会将栈顶(当前Activity)消灭,然后跳到下一层,不过此时在这个Activity中再次点击按钮创建对象时,它会另外创建新的Activity对象,这种模式可能大多数情况下不是我们需要的,因为对系统性能的消耗过大。
2、singleTop模式
singleTop模式在每次启动的时候会检测栈顶是不是要启动的activity,如果是,则不创建新的activity;否则,创建新的activity
3、singleTask模式
singleTask模式在每次启动的时候检测栈中是否存在将要启动的activity,如果存在,则会让要启动的activity之上的元素出栈,销毁要启动的activity之上的activity;如果不存在,创建出新的activity
4、singleInstance模式
singleInstance模式类似于浏览器,singleInstance模式在每次启动的时候会检测栈中是否存在将要启动的activity,如果存在,则将要启动的activity放到栈顶,确保至多有一个,与singleInstance不同的是,singleInstance模式不会销毁要启动的activity之上的activity。
此篇博客得益于法哥的一篇博客:/fanchangfa/archive//2657012.html,他已经写得非常详细了,我在此就不再赘述了。
阅读(...) 评论()深入理解Activity启动流程(三)–Activity启动的详细流程1 - 为程序员服务
深入理解Activity启动流程(三)–Activity启动的详细流程1
本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究。
本篇博客将开始介绍Activity启动的详细流程,由于详细启动流程非常复杂,故此分成两篇来介绍。
本篇主要介绍前半部分的启动流程:
1. Activity调用ActivityManagerService启动应用
2. ActivityManagerService调用Zygote孵化应用进程
3. Zygote孵化应用进程
下篇介绍后半部分的启动流程:
4. 新进程启动ActivityThread
5. 应用进程绑定到ActivityManagerService
6. ActivityThread的Handler处理启动Activity的消息
1. Activity调用ActivityManagerService启动应用
点击图片可看
在launcher应用程序里启动应用时,点击应用图标后,launcher程序会调用startActivity启动应用,传递的intent参数:
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(className);
activity最终调用Instrumentation的execStartActivity来启动应用:
//Activity类
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
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());
Instrumentation调用ActivityManagerProxy对象的startActivity方法启动Activity,而ActivityManagerProxy只是ActivityManagerService对象在应用进程的一个代理对象,ActivityManagerProxy最终调用ActivityManagerService的startActvity方法启动Activity。
//Instrumentation类
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
} catch (RemoteException e) {
2. ActivityManagerService调用Zygote孵化应用进程
点击图片可看
ActivityManagerProxy对象调用ActivityManagerService对象(运行在system_server进程)的startActivity方法以启动应用,startActivity方法接下来调用startActivityAsUser方法以启动应用。在startActivityAsUser方法里会调用ActivityStack的startActivityMayWait方法以启动应用,startActivityMayWait方法里启动应用时,需先根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,则会弹出ResolverActivity让用户选择合适的应用。
//ActivityStack类
final int startActivityMayWait(IApplicationThread caller, int callingUid,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
//根据intent在系统中找到合适的应用的activity,如果有多个activity可选择,
//则会弹出ResolverActivity让用户选择合适的应用。
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
startFlags, options, componentSpecified, null);
在startActivityLocked方法里,对传过来的参数做一些校验,然后创建ActivityRecord对象,再调用startActivityUncheckedLocked方法启动Activity。
startActivityUncheckedLocked方法负责调度ActivityRecord和Task,理解该方法是理解Actvity启动模式的关键。
startActivityUncheckedLocked方法调度task的算法非常复杂,和当前回退栈,要启动的acitivity的启动模式以及taskAffinity属性,启动activity时设置的intent的flag等诸多要素相关,intent的flag就有很多种情况,故此算法非常复杂,需要阅读源码并结合特定启动情况才能理解。
后续会介绍startActivityUncheckedLocked方法的实现,并结合特定场景分析调度算法。
接下来调用startActivityLocked将ActivityRecord加入到回退栈里:
//ActivityStack类
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
在startActivityLocked里调用resumeTopActivityLocked显示栈顶Activity:
//ActivityStack类
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
if (doResume) {
resumeTopActivityLocked(null);
resumeTopActivityLocked(null)会调用另一个resumeTopActivityLocked方法显示栈顶的acitivity:
//ActivityStack类
final boolean resumeTopActivityLocked(ActivityRecord prev) {
return resumeTopActivityLocked(prev, null);
因为应用还未启动过,所以调用startSpecificActivityLocked启动应用,执行逻辑如下:
//ActivityStack类
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (next.app != null && next.app.thread != null) {
startSpecificActivityLocked(next, true, true);
在startSpecificActivityLocked里调用mService.startProcessLocked启动应用:
//ActivityStack类
private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid);
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false);
在ActivityManagerService的startProcessLocked方法里:
//ActivityManagerService类
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated) {
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid);
if (app == null) {
app = newProcessRecordLocked(null, info, processName, isolated);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
mProcessNames.put(processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
startProcessLocked(app, hostingType, hostingNameStr);
在startProcessLocked方法里:
//ActivityManagerService类
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
// Start the process.
It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
//Zygote孵化dalvik应用进程后,会执行android.app.ActivityThread类的main方法
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
.targetSdkVersion, .seinfo, null);
} catch (RuntimeException e) {
在Process类的start方法里:
//Process类
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String[] zygoteArgs) {
startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
}catch (ZygoteStartFailedEx ex) {
在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。
3. Zygote孵化应用进程
点击图片可看
zygote进程将ZygoteInit作为启动类,会执行它的main方法,先注册ZygoteSocket,然后调用runSelectLoop方法,runSelectLoop方法会调用方法在ZygoteSocket上监听请求,如果别的进程通过ZygoteSocket请求孵化进程,则孵化进程。
runSelectLoop方法的主要代码:
//ZygoteInit类
private static void runSelectLoopMode() throws MethodAndArgsCaller {
while (true) {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
if (index & 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
//监听客户连接请求
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
//若客户发送孵化进程的请求过来,
//此时便需要调用ZygoteConnection的runOnce方法孵化进程
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
在runOnce方法里调用Zygote.forkAndSpecialize方法孵化进程,如果返回值为0表示是在孵化出来的应用进程里,此时会调用handleChildProc进行一些处理,并使用异常机制进行逃逸,会直接逃逸至ZygoteInit的main方法。
//ZygoteConnection类
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName);
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd =
//handleChildProc是一个很重要的函数,在该函数里使用了异常进行逃逸
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
} finally {
3.1 Zygote.forkAndSpecialize
Zygote的forkAndSpecialize方法会调用nativeForkAndSpecialize方法孵化进程,nativeForkAndSpecialize是一个本地方法,它的实现在dalvik/vm/native/dalvik_system_Zygote.cpp里,在该cpp文件里与nativeForkAndSpecialize对应的C++方法是Dalvik_dalvik_system_Zygote_forkAndSpecialize,在该方法里会调用forkAndSpecializeCommon孵化进程,在forkAndSpecializeCommon方法里会调用fork系统调用创建进程,因为使用的是fork机制所以创建进程的效率比较高。
3.2 handleChildProc
handleChildProc方法主要代码:
//ZygoteConnection类
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
if (parsedArgs.runtimeInit) {
String classN
//这里得到的classname实际是android.app.ActivityThread
className = parsedArgs.remainingArgs[0];
} catch (ArrayIndexOutOfBoundsException ex) {
logAndPrintError(newStderr,
"Missing required class name argument", null);
if (parsedArgs.invokeWith != null) {
if (parsedArgs.classpath != null) {
cloader = new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
cloader = ClassLoader.getSystemClassLoader();
//调用ZygoteInit.invokeStaticMain执行android.app.ActivityThread的main方法
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
ZygoteInit的invokeStaticMain方法并不会直接执行className的main方法,而是会构造一个 ZygoteInit.MethodAndArgsCaller异常,然后抛出来,通过异常机制会直接跳转到ZygoteInit的main方法, ZygoteInit.MethodAndArgsCaller类实现了Runnable方法,在run方法里会执行要求执行的main方法,故此跳转到ZygoteInit的main方法后,异常会被捕获,然后执行方法caller.run(),这样便会执行android.app.ActivityThread的main方法。
ZygoteInit的invokeStaticMain方法主要代码:
//ZygoteInit类
static void invokeStaticMain(ClassLoader loader,
String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
m = cl.getMethod("main", new Class[] { String[].class });
} catch(//...){
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
ZygoteInit.MethodAndArgsCaller主要代码:
public static class MethodAndArgsCaller extends Exception
implements Runnable {
public void run() {
mMethod.invoke(null, new Object[] { mArgs });
ZygoteInit的main方法相关代码:
//ZygoteInit类
public static void main(String argv[]) {
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
下面博客将介绍Activity详细启动流程的后半部分。
原文地址:, 感谢原作者分享。
您可能感兴趣的代码谈到Android的Activity组件,大家谈论最多的就是,而今天小编分享的则是启动模式相关知识。昨天在网上找Android Activity启动模式相关内容学习,找到一篇灰常实用的文章,仔细读来,赶脚真心牛叉,独乐了不如众乐乐,程序猿的精神就是重在分享,遂分享出来,大家一起学习学习吧。在中,Activity是四大组件之一,也是初学者必须重点掌握的内容之一,而要掌握Activity的启动模式,首先要学习的就是任务栈。任务栈是什么任务栈Task ,是一种用来放置Activity实例的容器,他是以栈的形式进行盛放,也就是所谓的先进后出,主要有2个基本操作:压栈和弹出,所以在其中只能根据压栈和弹出操作更改Activity的顺序。启动一个Application的时候,系统会为它默认创建一个对于的Task,用来放置根Activity。默认启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示它。当用户按下回退键时,这个Activity就会被弹出栈,按下Home键回到桌面,再启动另一个应用,这时候之前那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,Android系统显示的就是前台任务栈中的Top实例Activity。当然,同一个应用可以有多个任务栈,但是肯定只存在一个任务栈在前台。对于任务栈的调配应该大概了解了,下面提一下他的一个重要的属性taskaffinity,也就是所谓的亲和力。这个属性不仅Task有,Activity也有(affinity),他们就是通过这个属性值来进行关联的,不然一个应用有这么多Activity,并且可以有多个task,那么让activity实例随便入哪个栈都行,那岂不是乱成一团了。affinity系统默认会给他一个值,那就是应用的包名。并且如果自己重新给他值的话就在xml文件中定义,但是他的定义必须包含&.&,也就是像包名一样中间要有点号。Activity启动模式在安卓中,Activity的启动模式分为四种,分别是:标准模式,栈顶复用模式,栈内复用模式,单例模式。1、standard 即标准模式,他是系统默认的启动方式,这个任务栈中可以有多个相同的Activity实例,多个相同Activity实例也可以分布在不同的任务栈中,这时候是谁启动他,他就和谁在一个任务栈中。这时候我们要联系到我们遇到过的一个异常:android.util.AndroidRuntimeException:....,具体内容大家试试这样启动一个Activity就会出来,使用ApplicationContext启动一个standard模式的Activity。我们分析下,其实这个错误的出现就是因为默认模式下,被谁启动,activity就翻到那个任务栈中去,而全局的上下文对象是没有任务栈存在的,所以就会报错了。解决这个问题可以更改启动的上下文为某个activity对象,当然我们如果将被启动的activity设置他的标志位为FLAG_ACTIVITY_NEW_TASK 也同样可以,这时候就相当于把Activity改为了singleTask模式启动了。2、singleTop 即栈顶唯一模式,这种模式下,如果Activity位于任务栈的栈顶,那么此Activity不会被重新创建,也就是说 不会调用 生命周期中的 onCreate和onStart 方法,但是 会回调 另一个方法 onNewIntent ,这时候我们可以在这个回调方法里根据参数Intent intent进行自己的相关处理。如果新启动的Activity实例不存在,或者存在但是不是位于栈顶,那么和正常一样的创建它。3、singleTask 即栈内唯一,这个其实是一种单例模式,只要这个任务栈中存在Activity的实例,那么就不再创建它,而是直接复用其实例,这时候也会回调onNewIntent。这时候有个问题,这个实例如果不是在栈顶,那么它要到栈顶来,唯一途径就是把它之前的实例全部弹出,实际上就是说singleTask具有clearTop的效果。当然这是简单的说明,下面通过几个例子帮助大家更好的理解:例1.目前有S1任务栈中有ABC,这个时候要启动Activity D并且D是singleTask模式,其所需的任务栈为S2(之所以不是S1因为为他指定了affinity属性),这时候由于S2和D都不存在,所以会先创建任务栈S2,然后在创建实例D压入栈底。例2.情况和1相同,只是D所需任务栈同样是S1,这时候就只要创建D的实例并将其压入到栈S1中即可。例3.如果D所需的任务栈为S1,并且当前S1中的情况为ADBC,这时候D的实例存在了,那么会将BC出栈,剩下AD,这就是singleTask默认具有clearTop的效果4、singleInstance 单例模式,这是一种加强型的singleTask,他具有singleTask的所有特性,并且拥有一个独特的地方就是,他会单独占用一个任务栈,比如Activity A是singleInstance模式,那么启动他的时候,系统会为他单独创建一个任务栈将其压入,如果再次启动他,他已经存在了,那么就直接复用该任务栈。最后,需要提醒大家注意的一点就是TaskAffinity这个属性主要是与singleTask或者allowTaskReparenting属性配对使用,在其他情况下是没有意义的。Activity标志位Activity的标志位Flags有很多种,其效果也有很多,比如可以用来设定启动模式,可以用来影响运行状态,下面介绍几个常用的标志位:1、FLAG_ACTIVITY_NEW_TASK该标志位作用于指定Activity的singleTask启动模式一样。2、FLAGE_ACTIVITY_SINGLE_TOP该标志位的作用和指定Activity的singleTop效果一致。3、FLAGE_ACTIVITY_CLEAR_TOP此标记位的效果就有意思了,拥有它的Activity会将与他在同一个任务栈中之前Activity都出栈,这个标志通常和singleTask配合使用时,如果实例存在,就调用他的onNewIntent,并将他之上的其他实例都清除,但是如果拥有该标志位的Activity是默认启动模式standard,那么他会连同自己一起清除,然后再重新创建实例,这点要注意好,所以之前我们说了singleTask默认具有此标志的效果Activity设置启动模式的方式&&&&&&&在Android中,设置Activity的启动模式主要有以下两种方式:1、在XML文件中定义 android:launchMode=&singleTask&2、在启动意图的时候设置:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);上述这两种方式,在使用主要有以下两个区别:1、优先级优先级第二种大于第一种,当俩种方式同时存在的时候以第二种方式为准,第一种方式为辅。2、适用范围俩种方式也存在适用范围的区别,第一种方式无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标志的效果,而第二种方式无法直接设置出singleInstance模式的效果。&&&&&&以上就是Activity启动模式相关知识,个人感觉对老鸟们可能用处不大,但对于菜鸟们,还是有一些帮助的。相关文章:《》
(四川成都)
麦子学院,中国IT在线教育领导品牌,
小麦麦子的最新日记
······
&(1人喜欢)
······
如果让我来做毕业演讲 · 20条内容
你论文写完了吗? · 630条内容
最好的时代,最坏的时代 · 402条内容
就是那么简单几句我办不到 · 2351条内容
博物馆讲述难以言说的历史 · 362条内容
纪念汪老逝世二十周年 · 162条内容
推荐这篇日记的豆列
······
&(1人关注)本来想针对Activity中的启动模式写篇文章的,后来网上发现有人已经总结的相当好了,在此直接引用过来,并加上自己的一些理解,在此感谢原作者。
文章地址:
-------------------------------------------------------------------------------------------------
launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。
Activity一共有以下四种launchMode:
1.standard
2.singleTop
3.singleTask
4.singleInstance
我们可以在AndroidManifest.xml配置&activity&的android:launchMode属性为以上四种之一即可。
下面我们结合实例一一介绍这四种lanchMode:
1.standard
standard模式是默认的启动模式,不用为&activity&配置android:launchMode属性即可,当然也可以指定值为standard。
我们将会一个Activity,命名为FirstActivity,来演示一下标准的启动模式。FirstActivity代码如下:
1 package com.scott.
3 import android.app.A
4 import android.content.I
5 import android.os.B
6 import android.view.V
7 import android.widget.B
8 import android.widget.TextV
10 public class FirstActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
startActivity(intent);
我们FirstActivity界面中的TextView用于显示当前Activity实例的序列号,Button用于跳转到下一个FirstActivity界面。
然后我们连续点击几次按钮,将会出现下面的现象:
我们注意到都是FirstActivity的实例,但序列号不同,并且我们需要连续按后退键两次,才能回到第一个FristActivity。standard模式的原理如下图所示:
如图所示,每次跳转系统都会在task中生成一个新的FirstActivity实例,并且放于栈结构的顶部,当我们按下后退键时,才能看到原来的FirstActivity实例。
这就是standard启动模式,不管有没有已存在的实例,都生成新的实例。
简单点理解:standard启动模式Activity栈从栈底到栈顶顺序为A1 -& B -& C -& A2...。(其中A、B、C等都表示不同的Activity实例,A1、A2则表示属于具有同一Activity类的不同实例)
2.singleTop
我们在上面的基础上为&activity&指定属性android:launchMode="singleTop",系统就会按照singleTop启动模式处理跳转行为。我们重复上面几个动作,将会出现下面的现象:
我们看到这个结果跟standard有所不同,三个序列号是相同的,也就是说使用的都是同一个FirstActivity实例;如果按一下后退键,程序立即退出,说明当前栈结构中只有一个Activity实例。singleTop模式的原理如下图所示:
正如上图所示,跳转时系统会先在栈结构中寻找是否有一个FirstActivity实例正位于栈顶,如果有则不再生成新的,而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个Activity,如果是多个Activity怎么办,如果不是在栈顶会如何?我们接下来再通过一个示例来证实一下大家的疑问。
我们再新建一个Activity命名为SecondActivity,如下:
1 package com.scott.
3 import android.app.A
4 import android.content.I
5 import android.os.B
6 import android.view.V
7 import android.widget.B
8 import android.widget.TextV
10 public class SecondActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(this.toString());
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
startActivity(intent);
然后将之前的FirstActivity跳转代码改为:
1 Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
2 startActivity(intent);
是的,FirstActivity会跳转到SecondActivity,SecondActivity又会跳转到FirstActivity。演示结果如下:
我们看到,两个FirstActivity的序列号是不同的,证明从SecondActivity跳转到FirstActivity时生成了新的FirstActivity实例。原理图如下:
我们看到,当从SecondActivity跳转到FirstActivity时,系统发现存在有FirstActivity实例,但不是位于栈顶,于是重新生成一个实例。
这就是singleTop启动模式,如果发现有对应的Activity实例正位于栈顶,则重复利用,不再生成新的实例。
简单点理解,singleTop即表示当前Activity栈中&栈顶唯一&,Activity跳转顺序或standard模式下栈结构如果为:A -& B -& C -& D1 -& D2,则singleTop启动模式为:A -& B -& C -& D1(此时回调D1的onNewIntent()..)。
3.singleTask
在上面的基础上我们修改FirstActivity的属性android:launchMode="singleTask"。演示的结果如下:
我们注意到,在上面的过程中,FirstActivity的序列号是不变的,SecondActivity的序列号却不是唯一的,说明从SecondActivity跳转到FirstActivity时,没有生成新的实例,但是从FirstActivity跳转到SecondActivity时生成了新的实例。singleTask模式的原理图如下图所示:
在图中的下半部分是SecondActivity跳转到FirstActivity后的栈结构变化的结果,我们注意到,SecondActivity消失了,没错,在这个跳转过程中系统发现有存在的FirstActivity实例,于是不再生成新的实例,而是将FirstActivity之上的Activity实例统统出栈,将FirstActivity变为栈顶对象,显示到幕前。也许朋友们有疑问,如果将SecondActivity也设置为singleTask模式,那么SecondActivity实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次从SecondActivity跳转到FirstActivity时,SecondActivity实例都被迫出栈,下次等FirstActivity跳转到SecondActivity时,找不到存在的SecondActivity实例,于是必须生成新的实例。但是如果我们有ThirdActivity,让SecondActivity和ThirdActivity互相跳转,那么SecondActivity实例就可以保证唯一。
这就是singleTask模式,如果发现所在Activity栈中有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前。
简单点理解,singleTask表示当前Activity栈中&实例唯一&,Activity跳转顺序或standard模式下栈结构如果为:A -& B1 -& C -& D -& B2,则singleTask启动模式为:A -& B1(此时回调onNewIntent()..)
4.singleInstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。
我们修改FirstActivity的launchMode="standard",SecondActivity的launchMode="singleInstance",由于涉及到了多个栈结构,我们需要在每个Activity中显示当前栈结构的id,所以我们为每个Activity添加如下代码:
1 TextView taskIdView = (TextView) findViewById(R.id.taskIdView);
2 taskIdView.setText("current task id: " + this.getTaskId());
然后我们再演示一下这个流程:
我们发现这两个Activity实例分别被放置在不同的栈结构中,关于singleInstance的原理图如下:
我们看到从FirstActivity跳转到SecondActivity时,重新启用了一个新的栈结构,来放置SecondActivity实例,然后按下后退键,再次回到原始栈结构;图中下半部分显示的在SecondActivity中再次跳转到FirstActivity,这个时候系统会在原始栈结构中生成一个FirstActivity实例,然后回退两次,注意,并没有退出,而是回到了SecondActivity,为什么呢?是因为从SecondActivity跳转到FirstActivity的时候,我们的起点变成了SecondActivity实例所在的栈结构,这样一来,我们需要&回归&到这个栈结构。
此处的解释不是很赞同,第一次按Back键首先是在当前Activity栈中将栈顶元素出栈,然后显示当前Activity栈中下一个Activity栈,这个没什么解释的,然后按下Back键,不是回到手机桌面,而是回到另一个Activity栈中的SecondActivityInstance,我认为原因在于在于&最近栈&,只要此栈位于上次Home操作之后,就会先显示它。
如果我们修改FirstActivity的launchMode值为singleTop、singleTask、singleInstance中的任意一个,流程将会如图所示:
singleInstance启动模式可能是最复杂的一种模式,为了帮助大家理解,我举一个例子,假如我们有一个share应用,其中的ShareActivity是入口Activity,也是可供其他应用调用的Activity,我们把这个Activity的启动模式设置为singleInstance,然后在其他应用中调用。我们编辑ShareActivity的配置:
&activity android:name=".ShareActivity" android:launchMode="singleInstance"&
&intent-filter&
&action android:name="android.intent.action.MAIN" /&
&category android:name="android.intent.category.LAUNCHER" /&
&/intent-filter&
&intent-filter&
&action android:name="android.intent.action.SINGLE_INSTANCE_SHARE" /&
&category android:name="android.intent.category.DEFAULT" /&
&/intent-filter&
&/activity&
然后我们在其他应用中这样启动该Activity:
1 Intent intent = new Intent("android.intent.action.SINGLE_INSTANCE_SHARE");
2 startActivity(intent);
当我们打开ShareActivity后再按后退键回到原来界面时,ShareActivity做为一个独立的个体存在,如果这时我们打开share应用,无需创建新的ShareActivity实例即可看到结果,因为系统会自动查找,存在则直接利用。大家可以在ShareActivity中打印一下taskId,看看效果。关于这个过程,原理图如下:
原作者此处的解释可能有点让人误解。当我们打开ShareActivity后再按后退键回到原来界面时,ShareActivity做为一个独立的个体存在,此处不应该是按Back键,而是Home键,因为一旦按下了Back键,ShrareActivityInstance自然就销毁了,也就不存在所谓的&无须重新创建了&。按下Home键后,接下来打开app MainActivity,在另一个Activity栈中app MainActivity入栈,此时startActivity到ShareActivity,无需创建新的ShareActivity实例即可看到结果,因为系统会自动查找,存在则直接利用。此时第一次按下Back,ShareActivity Instance出栈,此时这个栈中没有其他Activity了,自然是回到了app MainActivity所在的栈并显示app MainActivity,接下来按Back键,此时app MainActivity所在的栈也没有其他Activity了,同时又不包含任何其他的&最近栈&,自然是回到了手机桌面。注:此处理解的&最近栈&是以Home键或桌面状态为间隔区分。
简单点理解,singleInstance所标识的Activity,当被启动时,系统会首先判断系统其他栈中是否已经存在此Activity实例,有则直接使用,并且其所在的Activity栈理论上只有它一个Activity元素。所以启动它的Activity与它并不在一个task中,所以才需要特别注意Back的问题。一般表示为:task1 A -& task2 B。
singleInstance表示该Activity在系统范围内&实例唯一&。由此我们发现,singInstance和singleTask主要区别在与系统范围内的&实例唯一&还是当前Activity栈&实例唯一&。
阅读(...) 评论()

我要回帖

更多关于 lol新手怎么玩 的文章

 

随机推荐