返回

startActivityForResult正确使用姿势

Android

startActivityForResult居然获取不到返回结果?

Android中Activity之间的跳转,有多种方式,比如使用Intent,包括显示启动和隐式启动,也可以使用Fragment的跳转方式,startActivityForResult是一种特殊的Intent方式。

startActivityForResult使用方法

为了能够在A页面收到B页面返回的数据,使用startActivityForResult启动Activity B,这个步骤跟普通的显示启动一样,只不过在Intent中设置了一个请求码和ResultActivity,请求码是标记该请求的唯一码,可以采用同一个请求码启动不同的页面,以便于在onActivityResult方法中识别,ResultActivity指明调用onActivityResult的页面是哪个,如果传入空的话,则onActivityResult将不会被调用。

/**
 * 跳转到第二个页面
 * @param requestCode 请求码
 * @param resultActivity 调用onActivityResult的页面,可以为空
 */
private void openSecondActivity(int requestCode, Activity resultActivity) {
    Intent intent = new Intent(this, SecondActivity.class);
    if (resultActivity != null) {
        startActivityForResult(intent, requestCode);
    } else {
        startActivity(intent);
    }
}

在跳转到B页面后,B页面拿到结果后,使用setResult方法设置返回结果,设置resultCode和Intent数据,resultCode同请求码的作用一样,用于在onActivityResult中识别结果,一般使用Activity.RESULT_OK和Activity.RESULT_CANCELED,Intent数据指明需要返回给A页面的数据。

/**
 * 设置返回结果
 * @param resultCode 请求码
 * @param intent 数据
 */
private void setResult(int resultCode, Intent intent) {
    setResult(resultCode, intent);
    finish();
}

最后在A页面onActivityResult方法中就可以获取到B页面的返回数据。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
        String result = data.getStringExtra("result");
        // 处理返回数据
    }
}

常用错误

上面就是startActivityForResult的正确使用姿势,但是日常开发中经常会遇到一些坑,比如onActivityResult根本不会被调用,这种情况一般是:

  • ResultActivity没有设置
  • 在B页面没有设置resultCode或setResult方法没有被调用
  • 调用startActivity方法启动页面
  • B页面使用Fragment进行跳转

除了上面介绍的四点以外,还有一种特殊情况:

A页面收到数据后,需要把数据返回给C页面,这时使用startActivityForResult直接跳到C页面,C页面onActivityResult不能获取数据。

这种情况是由Android系统提供的生命周期机制决定的,因为startActivityForResult会创建一个新的Activity栈,C页面不再A页面的Activity栈中,所以C页面无法获取到数据,这种情况应该使用以下方法:

  • 在C页面重写Activity的onNewIntent方法,在该方法中处理返回数据。
  • 使用AppLifecycleCallback监听Activity的生命周期,在onActivityResumed中处理返回数据。
  • 注册一个单例的全局对象,用于监听返回数据,在需要的时候回调数据。

总结

startActivityForResult是一种非常实用的功能,但也经常有坑,但是只要搞清楚原理,大部分坑都能轻松避开,希望本文对各位有所帮助。