lol新手怎么玩.activity启动器怎么玩

&&国之画&&&& &&
版权所有 京ICP备号-2
迷上了代码!一、Android的启动模式一共有四种:
Activity启动模式设置:
&activity android:name=&.MainActivity& android:launchMode=&standard& /&
Activity的四种启动模式:
1. standard
默认启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。
2. singleTop
如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
3. singleTask
如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。 如果在manifest中设置activity的launchMode为SingleTask或者是SingleTop 当activity任务栈存在该实例时,我们使用startActivity打开该activity时就会调用它的onNewIntent()方法而不是调用onCreate().
4. singleInstance
在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。
应用场景:
1.singleTop适合接收通知启动的内容显示页面。例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。聊天的对话窗口,
2.singleTask适合作为程序入口点。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。之前打开过的页面,打开之前的页面就ok,不再新建。
singleTask:a界面购物,b界面确认订单,c界面付款,如果付款成功会跳到a,如果不付款则返回b,这时候重启a就会用到singleTask.
3.singleInstance适合需要与程序分离开的页面。例如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -& B (singleInstance) -& C,完全退出后,在此启动,首先打开的是B。
4.standard 标准的启动模式,也是默认的启动模式。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4249次
排名:千里之外
原创:10篇查看: 7791|回复: 4
context的startActivity启动Activity以及背后的Task和Activity栈
该用户从未签到主题帖子e币
本帖最后由 琴弦第七 于
12:10 编辑
关于直接使用Context的satartActivity需要加Intent.FLAG_ACTIVITY_NEW_TASK标识后发送Intent才能启动Activity,以及这个标识引起的一些问题。
因为做毕业设计,设计了个程序结构,想使用一个service提供统一的逻辑接口来统一管理整个程序所有的组件,以方便以后程序功能的扩展。本来是想让service作为程序的启动入口,但是这么一来Android系统的程序列表中就没有这个程序的图标,反而没办法启动程序,所以还是用一个Activity做程序启动入口。顺便把这个Activity作为程序启动画面,然后再由这个Activity启动一个Service,以后就由这个Service来统一管理整个程序所有的组件,包括启动Activity之类的。
为了方便后面的解释,先说一下我的测试程序用到的两个activity和一个service:
1、MainActivity,程序的启动入口,目的是显示启动画面后启动service,主要只有一个onCreate方法:
[mw_shl_code=java,true]public class MainActivity extends Activity {
& && &&&@Override
& && &&&protected void onCreate(Bundle savedInstanceState) {
& && && && && & super.onCreate(savedInstanceState);
& && && && && & setContentView(R.layout.activity_main);
& && && && && & new Handler().postDelayed(new Runnable(){
& && && && && && && && &@Override
& && && && && && && && &public void run() {
& && && && && && && && && && &&&Log.i(Tag.TAG, &MainActivity Handler:id=&+getTaskId());
& && && && && && && && && && &&&MainActivity.this.startService(new Intent(IntentAction.CORESERVICE));
& && && && && && && && && && &&&MainActivity.this.finish();
& && && && && && && && && && &&&MainActivity.this.overridePendingTransition(R.anim.logoin, R.anim.logoout);
& && && && && && && && &}}, 5000);
}[/mw_shl_code]
2、CoreService,这个service启动后由它管理整个程序,现在用它来启动一个Activity:
[mw_shl_code=java,true]& && &&&public int onStartCommand(Intent intent, int flags, int startId) {
& && && && && & Intent intent2 = new Intent(this,ExportFile.class);
& && && && && & startActivity(intent2);
& && && && && & return super.onStartCommand(intent, flags, startId);
& && &&&}[/mw_shl_code]
3、ExprotFile,是个普普通通的Activity,由service来启动的Activity。
用service来管理其他组件,比如启动activity,本来以为是一件简单的事情,直接使用context的startActivity方法(service继承context)就行了。类似于Activity中的用法,直接用new Intent(Context,Class)构造个Intent,然后用Service的startActivity发送,如上面CoreService代码中所述,但是就出现了以下异常:
根据这个异常的提示,大意就是无法启动CoreService,因为CoreService要启动Activity没有使用Intent.FLAG_ACTIVITY_NEW_TASK标识。按照异常提示的方法,修改CoreService启动Activity的代码,加多标识:
[mw_shl_code=java,true]& && &&&public int onStartCommand(Intent intent, int flags, int startId) {
& && && && && & Intent intent2 = new Intent(this,ExportFile.class);
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
& && && && && & startActivity(intent2);
& && && && && & return super.onStartCommand(intent, flags, startId);
& && &&&}[/mw_shl_code]
毫无意外,service就能正常的启动一个Activity了。为什么Activity的startActivity不需要添加Intent.FLAG_ACTIVITY_NEW_TASK,而除了Activity之外的其它直接使用Context的startActivity方法就需要添加这个标识?
Activity的startActivity方法对Context的startActivity方法进行了重写,使其能够直接启动一个Activity,但是其它继承Context的组件没有,因此需要使用Intent.FLAG_ACTIVITY_NEW_TASK这个标识。那么这个标识会导致什么结果?从这个标识上看,两个关键单词:new task。因此,先来了解一下task是什么东东。
我们搞的都知道在Android里面,有一个叫Activity栈来管理Activity的东西,其实这个东西就是task,task以栈先进后出的管理方式来管理其中的Activity。每当一个程序启动的时候,android系统就会为这个程序创建一个task来管理这个程序用到的activity。从我们使用Android的体验来看,当我们打开一个程序,并进入这个程序的多个Activity之后,通过返回键就能够返回这个程序的上一个Activity,直到返回home,这就是因为task将这些activity以栈的方式管理导致的,task里面的activity栈返回到底变空了就回到了home。如果此时还没有回到桌面(task里的activity栈还没有空),就按home键回到桌面,启动了另一个程序,并且进入了这个程序中的多个activity,同样在这个程序中也可以用返回键返回上一个activity,直到桌面,但是却不会返回到之前那个程序,这说明两个程序使用的task不是同一个task。证明这个结论的另一个现象是此时再按home键回到桌面,再次单击第一个程序的图标进入程序,就会发现回到了第一程序按home键时的那个activity,而且还能够继续使用返回键返回。
需要注意的是,虽然一个程序启动的时候系统会为这个程序创建一个task供其使用,但是一个程序的task里面可以包含的activity也可以是非本程序的activity。比如我们经常遇到的打开了一个应用,这个应用里面有个电话号码,点击后可以调用系统拨号程序界面等待拨号,但是此时突然又不想打这个电话,就按了返回键,界面又回到了我们的应用,而不是home。可以看出在点击电话号码后,拨号程序拨号界面的activity被加入到我们应用的task里面。
文字有点多了,小结一下:一个程序启动后系统会为这个程序分配一个task供其使用,另外同一个task里面可以拥有不同应用程序的activity。那么,同一个程序能不能拥有多个task?这就涉及到加载activity的四种模式:standard、singleTop、singleTask、singleInstance。可以在AndroidManifest.xml中activity标签的属性launchMode中设置该activity的加载模式。简述下这四种模式的区别:
1、standard模式:默认的模式,以这种模式加载必定会构造一个新的Activity实例放到目标task中的activity栈顶,不管当前task的栈顶是什么情况。
2、singleTop模式:这种模式与standard模式类似,区别在于加载activity会多个判断步骤。判断需要加载的新activity与当前task栈顶的activity是不是同一个,相同的话就不再构造新的activity,并调用这个activity的newInstance()方法,不相同就还是会构造新的activity放到栈顶。
3、singleTask模式:这种模式下,会创建一个新的task来加载这个activity,并且这个task中只允许存在一个Activity的一个实例(以后可以加载其他activity的实例)。
4、singleTask模式:这种模式下,会创建一个新的task,并且这个task中只能存在一个需要加载的这个Activity实例,即除了这个activity之外,不允许其他activity。
从这四种Activity的加载模式中大概可以看出同一个程序可以拥有多个task。
是时候回到使用Intent.FLAG_ACTIVITY_NEW_TASK标识会有什么影响这个一开始的问题了。每一个task都有一个affinity属性,或者应该说每一个activity都有一个affinity属性,而task的affinity属性由task的根activity决定,这个affinity用来标识一个task,可以看做是一个task的id。activity的affinity属性可以在AndroidManifest.xml中的activity或者application标签(application标识application下所有的activity)的属性android:taskAffinity中设置。这个属性的属性值是一个字符串,默认情况下会使用继承元素的包名作为属性值。使用Intent.FLAG_ACTIVITY_NEW_TASK标识的时候,会先查看需要加载activity的affinity属性值。如果当前不存在相同affinity的task,那么就会创建一个新的task来加载这个activity。如果当前已经存在相同affinity的task,那么就不创一个新的,而是根据这个activity的加载模式加载到已存在的这个task中。
以下来验证一下这个结论,分别在activity中添加打印task id的方法:
1、MainActivity:
[mw_shl_code=java,true]public class MainActivity extends Activity {
& && &&&@Override
& && &&&protected void onCreate(Bundle savedInstanceState) {
& && && && && & super.onCreate(savedInstanceState);
& && && && && & setContentView(R.layout.activity_main);
& && && && && & new Handler().postDelayed(new Runnable(){
& && && && && && && && &@Override
& && && && && && && && &public void run() {
& && && && && && && && && && &&&Log.i(Tag.TAG, &MainActivity Handler:id=&+getTaskId());&&//打印ID
& && && && && && && && && && &&&MainActivity.this.startService(new Intent(IntentAction.CORESERVICE));
& && && && && && && && && && &&&MainActivity.this.finish();
& && && && && && && && && && &&&MainActivity.this.overridePendingTransition(R.anim.logoin, R.anim.logoout);
& && && && && && && && &}}, 5000);
}[/mw_shl_code]
2、ExportFile:
[mw_shl_code=java,true]public class ExportFile extends Activity {
& && &&&@Override
& && &&&protected void onCreate(Bundle savedInstanceState) {
& && && && && & // TODO Auto-generated method stub
& && && && && & super.onCreate(savedInstanceState);
& && && && && & setContentView(R.layout.activity_main);
& && && && && & Log.i(Tag.TAG, &ExportFile onCreate:id=&+getTaskId());&&//打印task ID
[/mw_shl_code]
运行后打印的日志:
发现打印出来的id不一样?我没有修改过AndroidManifest.xml中两个activity的testaffinity属性,属性值应该都是默认的包名。那么MainActivity启动的时候就应该分配到一个task,并且这个task的affinity属性由MainActivity的affinity属性值(也就是元素所在包名)决定,那么由Coreservice使用Intent.FLAG_ACTIVITY_NEW_TASK启动ExportFile这个Activity时,ExportFile的affinity值与MainActivity相同,应该不会重新建一个task才对。
导致这个问题的原因在于,我的代码中MainActivity启动CoreService之后,使用finish把自己给结束掉了,此时MainActivity所在的task已经空。当CoreService启动ExportFile时,虽然有个空的task,但是task的affinity由根Activity的affinity属性决定,所以当前已经找不到与ExportFile相同affinity属性的task,系统就会重新创建一个task导致了id的变化。
验证这个结论,MainActivity的finish语句注释掉,运行后打印日志:
可以看到id已经相同了,证明两个Activity都在同一个task里面,我按了返回键后也能回到MainActivity。
呼~打了两个多钟字,终于写完了。以上结论纯属个人琢磨结果,如有错误,欢迎指正,感激不尽。
参考资料:
/ghj1976/archive//2032495.html
http://blog.csdn.net/ghj1976/article/details/6371549
本帖子中包含更多资源
才可以下载或查看,没有帐号?
非常支持LZ的原创精神~
该用户从未签到主题帖子e币
這樣多得好得東西~~一定要學習~~也給大大按個贊
签到天数: 35 天连续签到: 1 天[LV.5]常住居民I主题帖子e币
好棒。。。学习喽~
该用户从未签到主题帖子e币
对于activity的几种launchMode LZ 还可看下
对于其他blog 来说 在天朝 不就是你抄我 , 我抄你,
曾经碰到一个问题 ,原始blog错了 结果导致N个blog全部错。
所以看 这个官网解释是最好的。
而且每个人看 这个英文都有自己的一个解释。呵呵&&没事可以看看
哈哈,好!我努力读读英文,感谢指导。&
该用户从未签到主题帖子e币
sk. 发表于
对于activity的几种launchMode LZ 还可看下 /guide/topics/manifest/activity ...
哈哈,好!我努力读读英文,感谢指导。
圣诞限量勋章
圣诞限量勋章
社区认证会员
社区认证会员
QQ已认证,此人靠谱
推荐阅读热门话题
61882419416380326280279260258251226218210206715
22&分钟前2&小时前2&小时前4&小时前5&小时前昨天&23:54昨天&22:16昨天&11:56昨天&10:35昨天&10:22昨天&01:22前天&23:16前天&16:58前天&15:58前天&15:09前天&14:55
Powered by你的位置: >
> Activity的四种启动模式-图文并茂
1、对于使用standard 模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。
例如A启动A,A再接着启动A,A继续启动A,然后再分别出栈,如图所示
2、当活动的启动模式指定为 singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
3、当活动的启动模式指定为 singleTask,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
4、使用singleInstance 模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。
假设B启动A,A启动C,其中A的启动模式为singleInstance,则:
返回的页面顺序是C-B-A
转载请注明: &
与本文相关的文章Android教程入门:停止和启动Activity
Stopping and Restarting an Activity
在activity生命周期中,恰当的停止与重启activity是很重要的,这样能确保用户感知到程序的存在并不会丢失他们的进度。在下面一些关键的场景中会涉及到停止与重启:
用户打开&最近使用的程序(Recent Apps)&的菜单并从当前app切换到另外一个app,这个时候先前的app是被停止的。如果用 户通过&主屏幕加载图标(Home screen launcher icon&或&最近使用的程序(Recent Apps)&重新回到这个app,则activity会重启。
用户在当前的app里面执行启动一个新的activity的操作时,当前activity会在第二个activity被创建后停止。如果用户点 击back按钮,之前的activtiy会被重启。
用户在运行app时接受到一个来电通话。
Activity类提供了onStop()方法与onRestart()方法用于在activity停止与重启时进行调用。和暂停状态时部分阻塞用户接口不同,停止状态时UI不可见并且用户的焦点转移到另一个activity中。
注意:&因为系统在Activity停止时会在内存中保存了Activity实例,所以很多时候不需要实现onStop()方法与onRestart()方法,甚至是onStart()方法。 因为大多数的Activity相对比较简单,Activity会自动正常停止与重启,只需要使用onPause()来停止正在运行的动作并断开系统资源链接。
如图1所示:当用户离开Activity时系统会调用onStop()来停止Activity (1)。这个时候如果用户返回,系统会调用onRestart()(2), 紧接着会调用onStart()(3)与onResume()(4)。需要注意的是:无论什么原因导致Activity停止,系统总是会在onStop()之前调用 onPause()方法。
停止Activity
当activity调用onStop()方法时,该activity不再可见并且应该释放所有不再需要的资源。一旦activity停止了,系统可能会摧毁activity的实例以回收内存,甚至,系统会不执行activity的onDestroy()回调方法而直接杀死你的app进程, 因此需要使用onStop()来释放资源,从而避免内存泄漏。
尽管onPause()方法是在onStop()之前调用,通常应该使用onStop()来执行CPU密集型的关闭操作,例如把数据写入数据库。
例如,下面是一个在onStop()的方法里面保存笔记草稿到永久存储介质的示例:
当Activity已经停止,Activity对象会保存在内存中,并且在Activity恢复的时候被重新调用到。不需要在恢复到Resumed state状态前重新初始化那些被保存在内存中的组件。系统同样保存了每一个在布局中的视图的当前状态,如果用户在EditText组件中输入了文本,也会被保存,因此不需要保存与恢复它。
注意:&即使系统会在Activity停止的时候销毁这个Activity,系统仍然会保存视图对象(如文本编辑框中的文本)到一个Bundle中,并且在用户返回这个Activity时恢复他们(下一节会介绍在Activity销毁与重建时如何使用Bundle来保存其他数据的状态)。
启动与重启Activity
当Activity从Stopped状态回到前台时会调用onRestart(),系统再调用onStart()方法,onStart()方法在每次Activity可见时都会被调用。onRestart()方法则是只在Activity从stopped状态恢复时才会被调用,因此可以使用它来执行一些特殊的恢复工作,请注意之前是被stop而不是destrory。
使用onRestart()来恢复Activity状态并不常见,因此对于这个方法如何使用没有指导说明。但是,由于onStop()方法要做清除所有Activity资源的操作,在重新启动Activtiy时需要重新实例化被清除的资源,同样,在Activity第一次创建时要实例化那些资源。因为系统会在创建Activity与从停止状态重启Activity时都会调用onStart(),应该使用onStart()作为onStop()所对应的方法。
例如:因为用户很可能在回到Activity之前需要过一段时间,所以onStart()方法是一个比较好的用来验证某些必须的功能是否已经准备好的地方。
微信扫一扫
您好,感谢关注凌阳教育,如果您要索取免费技术资料,请点击此处留言,谢谢!

我要回帖

更多关于 多玩我的世界启动器 的文章

 

随机推荐