可悲的是,ActivityCompat.startActivityForResult() 在Fragments 中不能正常工作(请参阅 Alex Lockwood 的回答)。几个星期以来,我都惊叹于 Google 从未给我们提供与 Fragment 的 startActivityForResult() 实现等效的 ActivityCompat 方法。他们在想什么?!但是后来我有了一个想法:我们来看看这个方法是怎么实现的。
事实上,Fragment 中的startActivityForResult() 与 Activity 中的不同(参见here):
public void startActivityForResult(Intent intent, int requestCode) {
if (mActivity == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
mActivity.startActivityFromFragment(this, intent, requestCode);
}
现在startActivityFromFragment() 看起来像这样(参见here):
public void startActivityFromFragment(Fragment fragment, Intent intent,
int requestCode) {
if (requestCode == -1) {
super.startActivityForResult(intent, -1);
return;
}
if ((requestCode&0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
}
super.startActivityForResult(intent,
((fragment.mIndex + 1) << 16) + (requestCode & 0xffff));
}
Google 对请求代码使用了一些奇怪的字节移位,以确保之后仅调用调用 Fragment 的 onActivityResult()。现在由于ActivityCompat 没有提供任何startActivityFromFragment(),剩下的唯一选择就是自己实现它。访问包私有字段mIndex需要反射。
public static void startActivityForResult(Fragment fragment, Intent intent,
int requestCode, Bundle options) {
if (Build.VERSION.SDK_INT >= 16) {
if ((requestCode & 0xffff0000) != 0) {
throw new IllegalArgumentException("Can only use lower 16 bits" +
" for requestCode");
}
if (requestCode != -1) {
try {
Field mIndex = Fragment.class.getDeclaredField("mIndex");
mIndex.setAccessible(true);
requestCode = ((mIndex.getInt(this) + 1) << 16) + (requestCode & 0xffff);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
ActivityCompat.startActivityForResult(fragment.getActivity(), intent,
requestCode, options);
} else {
fragment.getActivity().startActivityFromFragment(this, intent, requestCode);
}
}
将该方法复制到您喜欢的任何地方并从您的 Fragment 中使用它。它的onActivityResult() 将被调用。
更新:
支持库 v23.2 已发布,似乎 startActivityFromFragment(Fragment fragment, Intent intent, int requestCode, Bundle options) 现在可以完成这项工作:)