android的启动模式 到底在什么时候用呢?

安卓的启动模式 估计都学过 但好长时间内不知道怎么用,感觉都忘了启动模式的存在了,一般都是默认的模式, 然后通过Intent跳转 的时候呢 执行以下finish();感觉挺好用,但是也不能完全符合我们的需求。

涉及的内容

  • 四种启动模式是什么,在哪里用
  • onNewIntent() 是什么

一句话理解四种启动模式(网上太多了)

  • standard:每次启动activity都会创建一个activity实例,不管它是否存在

  • singleTop:当启动activity的时候,如果该activity不在栈顶,会创建一个activity实例,如果他在栈顶存在,执行他的onNewIntent()

  • singleTask:第一次启动创建实例,以后再启动执行他的onNewIntent()操作,并销毁栈中在他上面的其他实例

  • singleInstance():第一次启动创建实例,在启动执行onNewIntent(),并且单独在一个栈中。

发现重复最多的就是onNewIntent()了。

onNewIntent()是什么

他是什么我说的也不算看代码

<code class="hljs applescript has-numbering">    /**
     * This <span class="hljs-keyword">is</span> called <span class="hljs-keyword">for</span> activities <span class="hljs-keyword">that</span> <span class="hljs-keyword">set</span> launchMode <span class="hljs-keyword">to</span> <span class="hljs-string">"singleTop"</span> <span class="hljs-keyword">in</span>
     * their package, <span class="hljs-keyword">or</span> <span class="hljs-keyword">if</span> a client used <span class="hljs-keyword">the</span> {@link Intent<span class="hljs-comment">#FLAG_ACTIVITY_SINGLE_TOP}</span>
     * flag when calling {@link <span class="hljs-comment">#startActivity}.  In either case, when the</span>
     * activity <span class="hljs-keyword">is</span> re-launched <span class="hljs-keyword">while</span> <span class="hljs-keyword">at</span> <span class="hljs-keyword">the</span> top <span class="hljs-keyword">of</span> <span class="hljs-keyword">the</span> activity stack instead
     * <span class="hljs-keyword">of</span> a new instance <span class="hljs-keyword">of</span> <span class="hljs-keyword">the</span> activity being started, onNewIntent() will be
     * called <span class="hljs-function_start"><span class="hljs-keyword">on</span></span> <span class="hljs-keyword">the</span> existing instance <span class="hljs-keyword">with</span> <span class="hljs-keyword">the</span> Intent <span class="hljs-keyword">that</span> was used <span class="hljs-keyword">to</span>
     * re-<span class="hljs-command">launch</span> <span class="hljs-keyword">it</span>.
     *
     * <p>An activity will always be paused <span class="hljs-keyword">before</span> receiving a new intent, so
     * you can <span class="hljs-command">count</span> <span class="hljs-function_start"><span class="hljs-keyword">on</span></span> {@link <span class="hljs-comment">#onResume} being called after this method.</span>
     *
     * <p>Note <span class="hljs-keyword">that</span> {@link <span class="hljs-comment">#getIntent} still returns the original Intent.  You</span>
     * can use {@link <span class="hljs-comment">#setIntent} to update it to this new Intent.</span>
     *
     * @param intent The new intent <span class="hljs-keyword">that</span> was started <span class="hljs-keyword">for</span> <span class="hljs-keyword">the</span> activity.
     *
     * @see <span class="hljs-comment">#getIntent</span>
     * @see <span class="hljs-comment">#setIntent</span>
     * @see <span class="hljs-comment">#onResume</span>
     */
    protected void onNewIntent(Intent intent) {
    }
</code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div>

onNewIntent()什么时候执行?(对了,他可不是生命周期,他就为了长得跟生命周期很像,容易混个脸熟而已)

  • 你得执行intent跳转的时候。(比如什么后台重新启动,在他栈顶的xxActivity 被finish() 然后显示他的,都没执行intent跳转,返回键回退栈。都不会走onNewIntent())
  • 启动模式是singletop(当前activity在栈顶,), singletask(不管在栈的哪里),启动后再次启动

onNewIntent()执行了,activity的生命周期是怎样的呢?

  • 只要执行onNewIntent(),必须就执行intent操作,那肯定当前activiy的onPause()先执行,所以 当前的activity 如果想跳转到自己 并且是singletop的时候执行顺序
    onCreate()
    onStart()
    onResume()
    点击跳转到自己
    onPause()
    onNewIntent()
    onResume()(这里并没有onStop)
  • 还有一种情况就是 app1 和app2 是两个 软件,也就是连个进程,他们分别都有一个activiy。

    当他们的启动模式是standard或者是singletop的时候 现在执行的顺序是:
    开启app2 ,按下home键,开启app1,点击按钮跳转app2
    生命周期是:
    app2 onCreate(开启app2)
    app2 onStart
    app2 onResume
    app2 onPause(按下home键)
    app2 onStop
    app1 onCreate(开启app1)
    app1 onStart
    app1 onResume
    app1 onPause(app1 跳转到app2)
    app2 onCreate
    app2 onStart
    app2 onResume
    app1 onStop

可以看到app2的activity虽然已经在后台了但是依然创建了,下面看一下结构
在cmd里面打 adb shell dumpsys activity 这句话

Running activities (most recent first):
TaskRecord{537b7d08 #44 A com.app1 U 0}
Run #4: ActivityRecord{53651f18 com.app2/.MainActivity}
Run #2: ActivityRecord{5376a210 com.app1/.FirstActivity}
TaskRecord{536c9a5c #2 A com.android.launcher U 0}
Run #1: ActivityRecord{536c8bec com.android.launcher/com.android.launcher2.Launcher}
TaskRecord{53782c88 #42 A com.app2 U 0}
Run #0: ActivityRecord{53768f08 com.app2/.MainActivity}

有三个线程,ui线程,app1 和app2,发现 在#44进程里面出现了 app2的身影。

同样的条件只把 启动模式改为 singleTask或者是singleInstance的话
app2 onCreate
app2 onStart
app2 onResume
app2 onPause(按下home按键)
app2 onStop
app1 onCreate(开启app1)
app1 onStart
app1 onResume
app1 onPause(app1 跳转到app2)
app2 onNewIntent
app2 onRestart
app2 onStart
app2 onResume
app1 onStop

可以发现app2的onNewIntent()执行了。那么看下结构

Running activities (most recent first):
TaskRecord{536b469c #48 A com.app2 U 0}
Run #3: ActivityRecord{5364a00c com.app2/.MainActivity}
TaskRecord{536d82a4 #49 A com.app1 U 0}
Run #2: ActivityRecord{53696ad4 com.app1/.SecondActivity}
Run #1: ActivityRecord{536d6234 com.app1/.FirstActivity}
TaskRecord{536c9a5c #2 A com.android.launcher U 0}
Run #0: ActivityRecord{536c8bec com.android.launcher/com.android.launcher2.Launcher}

可以看到app2的activity并没有出现在app1的栈里面。

所以啊:区别就来了 standard和singletop处于一个集团,他们在一个app跳刀另一个app的时候都会创建新的activity实例, 并且他们都在一个堆栈中,singleTask和singleInstance处于一个集团,他们在app跳刀app的时候都不会产生新的实例,在这种情况下也不会和其他app在一个栈中。(有什么用呢,在用启动模式的时候能理解更加深刻别误以为 onNewIntent肯定会实现,哥就进坑了)

四种启动模式什么时候用呢?(把网上找的基本都测了一遍+自己的感悟吧)

我觉得吧,作为一个程序员在写代码的时候就要先高屋建瓴的感知一下你要写的项目是怎样的,需求是怎样的,提前想好了用什么启动模式,这样才避免启动模式改来改去。

  • standard:这个基本不用说啦,其实大多数的时候都用它,我以前都是用intent各种跳转,跳转的时候把activity给finish()了,然后回退栈的时候在进行跳转 在finish() 这个好累呀。但作为菜鸟的我这样了很久。

  • singleTop:
    1.适合接收通知启动的内容显示页面。
    比如新闻客户端收到了100个推送,你每次点一下推送他都会走一遍某个activiy(显示新闻只用一个activity,只是内容不同而已)的oncreate,onstart,代价就是创建了那么多的activity(不要以为只有推送,比如qq消息提醒)
    a,耗内存
    b, 走了100次的跳转动画 ,也是醉了

    • 但是要注意啊,从其他app跳转到singletop的app的时候是不会走onNewIntent的 上面提到了,所以遇到app相互调用的时候很少用singletop。

    2.某些业务需求是自己的activity跳转到自己的。
    比如 歌曲搜索 你又不会用actionbar,toolbar,那就在activity上面弄个假的呗,搜索完了自己跳转自己现实搜索结果,那就直接用该模式,变化都在onNewIntent()里面对空间进行 赋值之类的。而且也没有跳转动画,人们以为这个activity没有动了,多high。

Intent.FLAG_ACTIVITY_SINGLE_TOP 至于这个问题 它的作用等于singletop,他就管一次,除了activity自己跳转自己,还没想过哪里用,因为两个进程之间跳转 是不走onNewIntent()的。

  • singleTask:(我记得第一次面试问的就是开100个activity如何快速关闭)
    1,适合程序开始的activity(频繁使用的主架构)
    可以用于主架构的activity,(什么新闻啊,侧滑啊)里面有好多fragment,他一般不会被销毁,他可以跳转其他的activity 再回主架构 其他的就销毁呗

        浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。(忘了从哪看得了)
    
        比如登陆页面也是 入口 那就没太大必要,因为不经常用啊。finish()算了
    

那么问题来了 如果你担心主架构用singleTask以后是否会有问题,那又想一下子删除好多activity,那就这样两个一起来
Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
清除其他的activity而且只管一次
单独用的话我就没 实现过他说的功能 感觉比较坑,一起用最稳。

  • singleInstance :他只做一件事情
    他的任务栈好复杂呀,我的理解 他只做一件事情就够了
    比如 闹钟里面 负责响的页面,打电话 接通的时候,地图显示的时候,他们都有一个特点 就是你做完这件事了都会返回到上一界面 而没有下一界面。
    最好不要把 singleInstance 放到 中间的activity里面
    a->b->c 如果 b是该启动模式, 那么 a ,c在一个栈里面 b 在一个栈里面,那你如果回退的话就悲剧啦,用户也会感觉奇怪。所以我理解 最好不要 让singleInstance 跳转到其他activity,当然也不绝对。

注意:如果你每次都在oncreate()加载数据 (有变化的都算)那就没法用啦, 或者加载数据的地方在oncreate()和onNewIntent()全写一遍。因为你在后台的话很可能被杀死啦,那你预计让他走onNewIntent() 可能他就走了onCreate()了。

一些常用的flag组合(没写的是我很少用,没有发言权呀)

  • Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
    这个activity新启动一个栈,原来栈被清空,栈中的activity也被销毁。
  • Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP
    a->b ->a 其中b是以此方法跳转的,b销毁,a走onNewIntent()方法。 比较常用
    b只用 Intent.FLAG_ACTIVITY_CLEAR_TOP: a b都销毁 重建a

就这些吧 , 没有图 叙述比较多 ,看完了比较辛苦,希望能更加深刻的理解 这些个启动模式在什么时候用,水平有限欢迎指责,有更好的应用场景欢迎 评论

(http://blog.csdn.net/wanghao200906/article/details/49766309)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值