SingleTask使用时遇见的坑(1)

是时候重新了解一下启动模式了。
项目中遇到的启动模式的坑的确是差点颠覆了我的认知,就比如SingleTask来说吧,举个例子,此时有ActivityA,ActivityB,ActivityC,他们都是同一进程下的Activity,A和C 的启动模式是Standard,B是SingleTask的,那么A通过StartActivity启动B,B在通过StartActivity启动C,此时任务栈内的情况是"A B C",那么C通过StartActivity启动B时,由于B在任务栈内存在,因此B之上的C将弹出,B成为栈顶。没错,到这里还是很正确的。那么,如果C通过startActivityforResult的方式去启动B呢, 我们利用startActivityforResult的方式就是为了能让B返回结果给C,但现在B是SingleTask的模式,会把C给弹出栈,那这个结果返回给谁呢???
哇,说实话之前没想过竟然还有这样的问题,其实结果很简单,B的SingleTask强制无效了呗(至少我遇到的情况是这样的),B会变成standard模式启动一样。网上还有人说,在4.4之前,在startActivityForResult时,我们传入的RequestCode会返回为RESULT_CANCEL,且我们的onActivityResult会立即执行,而不是B通过setResult时才执行。在4.4之后就会出现我遇到的情况。以后有时间会深究以下,暂且记录到这里。(其实说的好像有问题,等研究好了在改正吧,singleinstance也会出现这样的问题)。

补充(今天自己动手写了demo测试了下,API26,Android 7.0), startActivityForResult()启动一个启动模式为SingleTask的Activity时,SingleTask无效,该Activity会以默认模式启动从而使onActivityResult可以收到结果。
原因的话,找到了这样一段代码:

            if (top != null && r.resultTo == null) {
                Slog.d("DDY", "========------ " );
                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                    if (top.app != null && top.app.thread != null) {  
                             ..........
                              ..........
                              ...........//此处省略一万行代码。。。                  
                            top.deliverNewIntentLocked(callingUid, r.intent);         
            }
        } else {
            if (r.resultTo != null) {
                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
                        r.requestCode, Activity.RESULT_CANCELED, null);
            }
       

上述代码是AMS中关于启动Activity的代码,deliverNewIntentLocked这句话是主要调用onNewIntent的,而else后面则是按照默认的启动模式(即Standard)来启动Activity的。那么我们什么时候能调用到deliverNewIntentLocked,这里面有很多判断逻辑,我们这里只看最外部的大判断即可。top != null && r.resultTo == null,这一句里首先判断top!=null,即判断当前栈顶activity是不是空,一般都不为空,所以看第二个条件 r.resultTo == null,这里r.resultTo其实就是判断我们是否有返回的结果,如果我们使用startActivity,r.resultTo就为空,此时我们的singletask会正常使用,从而调用到onNewIntent()的方法。但如果我们使用startActivityForResult(),此时r.resultTo!=null,这时就不会进入循环内部,而是直接调用后面的逻辑,从而当做默认启动模式启动。

你可能感兴趣的:(SingleTask使用时遇见的坑(1))