天天看点

launchMode带来的onActivityResult失效问题

  项目开发中遇到一个问题,由ActivityA跳转到ActivityB时,如果ActivityB设置了launchMode,并且B界面finish时需要返回给ActivityA一些数据,这时候ActivityA对于ActivityB的onActivityResult()方法可能会出现一些问题。下面写一个简单的小demo来验证一下。

  A中有一个按钮进行界面跳转到B,

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(A.this,B.class);
                startActivityForResult(intent,REQUST_CODE);
            }
        });
           

  B中按钮finish,返回A界面。

finish.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("test", "data from B");
                setResult(RESULT_OK,intent);
                finish();
            }
        });
           

  最后在A中进行处理,

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode==RESULT_OK){
            String result=data.getStringExtra("test");
            Toast.makeText(getApplicationContext(),"RESULT_OK  "+result,Toast.LENGTH_SHORT).show();
        }

        if (resultCode==RESULT_CANCELED){
            Toast.makeText(getApplicationContext(),"RESULT_CANCELED",Toast.LENGTH_SHORT).show();
        }
    }
           

  关于launchMode就不详细讲解了,这里简单说一下。

standard:默认的启动模式,每次启动都会在当前栈中重新生成一个新的 Activity实例。

singleTop:启动时先去检查栈顶是不是当前Activity实例,是的则直接使用,不 是的就重新创建。

singleTask:保证当前栈中只有自己的一个实例,通常的做法是,如果在栈中发现了自己的Activity实例,就将这个实例之上的其他Activity实例统统赶走,使自己成为栈顶。

singleInstance:这个模式最霸道,会重新建一个栈,把自己的Activity实例放进去,并且不会再放入其他Activity实例。

  先测试一下standard模式,清单文件ActivityB中加入

android:launchMode="standard"

,断点调试。点击A中按钮,跳转到B,点击B中按钮,进入断点,如下图所示,这是A成功收到B返回过来的数据,standard模式启动Activity对onActivityResult没有影响。

launchMode带来的onActivityResult失效问题

  接下来以同样的方式测试singleTop模式,测试结果与standard模式一样,这里不再赘述。

  接着将B的启动模式改为singleTask继续断点测试,这次结果就比较出人意料,与之前有很大区别。当我点击A中跳转按钮时,就直接进入了onActivityResult中的断点,注意这里进入断点的时间,并不是点击B中finish按钮后才进入断点。这里我就产生了一个疑惑,当我点击按钮去进行跳转按钮之后,是不是压根就没有进入B界面。为了验证一下这个问题,我在B界面的onCreate()方法上也打上断点,来看一下代码的执行顺序。这次,当我点击A中按钮后。首先执行的依然是A中的onActivityResult方法,那么此时的resultCode是多少呢?请注意看下图,

launchMode带来的onActivityResult失效问题

  可以看到此时的resultCode是一个值为0的常量,RESULT_CANCELED,所以这样是完全没有办法接收数据的,也就是在调用startActivityForResult()之后就直接调用了onActivityResult(),并给出了一个值为0的结果码。至于具体原因,暂时还没有想到比较合理的解释,哪位大牛知道原因的和小弟说道说道。

  最后来测试一下singleInstance模式,发现和singleTask模式一样。

  所以,如果当你要跳转的Activity的启动模式为singleTask或者singleInstance时,会导致跳转前Activity无法收到跳转后Activity返回的数据,在这里要注意一下。

继续阅读