SingleTask与onActivityResult之间关系的简单讨论

⚠️注意:在API22的情况下验证通过,在API18/19 上均验证失败

很多博客里说,在LaunchMode设置为SingleTask之后,是调用方的onActivityResult会在打开的瞬间被调用,无法取得正常的结果,因此来验证一下。

概括


以下大写字母均表示为Activity.
->代表startActivity =>代表startActivityForResult
第一个场景:
A=>B A打开B,并需求返回值
B=>C B打开C,并需求返回值
C->B C打开B(准确来说是返回A打开的B)
因此,我需要将B设置为SingleTask,那么在C打开B的时候,直接将B置为栈顶,并将C出栈,达到效果。

Demo代码


MainActivity

public class MainActivity extends AppCompatActivity {

    public static final int REQUEST_CODE_SECOND_ACTIVITY = 0x1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void start(View view) {
        startActivityForResult(new Intent(this,SecondActivity.class), REQUEST_CODE_SECOND_ACTIVITY);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){
            case REQUEST_CODE_SECOND_ACTIVITY:
                if(null != data){
                    final String data1 = data.getStringExtra("data");
                    ((TextView) findViewById(R.id.tv_result)).setText(data1);
                }
                break;
            default:
                super.onActivityResult(requestCode, resultCode, data);
        }
    }
}

SecondActivity

public class SecondActivity extends Activity {

    public static final int REQUEST_CODE_THIRD_ACTIVITY = 0x1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    public void start(View view) {
        startActivityForResult(new Intent(this,ThirdActivity.class), REQUEST_CODE_THIRD_ACTIVITY);
    }

    @Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("data","result from SecondActivity");
        setResult(RESULT_OK, intent);

        super.onBackPressed();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode){
            case REQUEST_CODE_THIRD_ACTIVITY:
                if(data != null){
                    final String data1 = data.getStringExtra("data");
                    ((TextView) findViewById(R.id.tv_result)).setText(data1);
                }
                break;
            default:
                super.onActivityResult(requestCode, resultCode, data);
        }
    }
}

ThirdActivity

public class ThirdActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
    }

    public void start(View view) {
        Intent intent = new Intent(this,SecondActivity.class);
        startActivity(intent);
    }
}

AndroidManifest.xml

<activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            intent-filter>
        activity>

        <activity android:name=".SecondActivity" android:launchMode="singleTask"/>
        <activity android:name=".ThirdActivity"/>

代码很基础,就不做解释了,需要注意的是SecondActivity的LaunchMode为SingleTask。

运行(运行结果下方为adb shell dumpsys activity的部分结果)


1.程序打开,进入MainActivity,点击按钮进入下一步

SingleTask与onActivityResult之间关系的简单讨论_第1张图片
MainActivity 第一次

2.进入SecondActivity,点击按钮进入下一步

SingleTask与onActivityResult之间关系的简单讨论_第2张图片
SecondActivity 第一次

3.进入ThirdActivity,点击按钮打开LaunchMode为SingleTask的SecondActivity

SingleTask与onActivityResult之间关系的简单讨论_第3张图片
ThirdActivity 第一次

4.进入SencondActivity,点击返回按钮,进入MainActivity,代码中在返回回调中加入setResult(RESULT_OK,intent),传递返回数据到MainActivity

SingleTask与onActivityResult之间关系的简单讨论_第4张图片
SecondActivity 第二次

5.返回到MainActivity,可以看到有返回值

SingleTask与onActivityResult之间关系的简单讨论_第5张图片
MainActivity 第二次

根据以上运行结果和栈的变动情况可以看出,自始至终,所有的Activity均在同一个Task之后,没有新的Task创建。这点观察ActivityRecord末尾t开头的那串字符,那是Task的编号。
因此说SingleTask就不能使用onActivityResult()是没有道理的。

那么什么情况下,onActivityResult()不能够正常的返回结果呢?

在AndroidManifest.xml中,声明Activity的时候,可以添加android:taskAffinity=”:a”,这个配合SingleTask使用可以使Activity加入在以taskAffinity为名称的栈内,那么如果不在同一个栈内,onActivityResult()应该就不能获得正确的结果了吧。

在加入taskAffinity之后,笔者发现一个奇怪的事情,在使用startActivityForResult去开启Activity的时候,并不能让打开的Activity(launchMode=”singleTask”)在一个新的栈中,然而使用startActivity()就可以。

剩下的验证就留给读者自己去验证了,毕竟实践之后,印象会更加深刻一些。

总结


  • 使用SingleTask也能获取onActivityResult,只要在同一个Task之中。
  • 设置了taskAffinity之后,如果使用startActivityForResult()打开Activity,那么会忽略taskAffinity的效果,不会将打开的Activity置入以taskAffinity为命名的任务栈中;如果使用startActivity()方式打开,那么会新建一个以taskAffinity为命名的任务栈,并将打开的Activity置于其中。

你可能感兴趣的:(android)