startActivityForResult() 被弃用问题
之前说过启动另一个 activity 可以通过用 Activity 类提供的 startActivityForResult() 和 onActivityResult() 的 API 来获取另一个 activity 返回的结果,但是现在我们现在会发现使用这样的 API 产生了错误提示。
'startActivityForResult(Intent!, Int): Unit' is deprecated
/**
* Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's
* containing Activity.
*
* @param intent The intent to start.
* @param requestCode The request code to be returned in
* {@link Fragment#onActivityResult(int, int, Intent)} when the activity exits. Must be
* between 0 and 65535 to be considered valid. If given requestCode is
* greater than 65535, an IllegalArgumentException would be thrown.
* @param options Additional options for how the Activity should be started. See
* {@link Context#startActivity(Intent, Bundle)} for more details. This value may be null.
*
* @deprecated use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* passing in a {@link StartActivityForResult} object for the {@link ActivityResultContract}.
*/
@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated
public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
int requestCode, @Nullable Bundle options) {
if (mHost == null) {
throw new IllegalStateException("Fragment " + this + " not attached to Activity");
}
getParentFragmentManager().launchStartActivityForResult(this /*fragment*/, intent,
requestCode, options);
}
/**
* Receive the result from a previous call to
* {@link #startActivityForResult(Intent, int)}. This follows the
* related Activity API as described there in
* {@link Activity#onActivityResult(int, int, Intent)}.
*
* @param requestCode The integer request code originally supplied to
* startActivityForResult(), allowing you to identify who this
* result came from.
* @param resultCode The integer result code returned by the child activity
* through its setResult().
* @param data An Intent, which can return result data to the caller
* (various data can be attached to Intent "extras").
*
* @deprecated use
* {@link #registerForActivityResult(ActivityResultContract, ActivityResultCallback)}
* with the appropriate {@link ActivityResultContract} and handling the result in the
* {@link ActivityResultCallback#onActivityResult(Object) callback}.
*/
@SuppressWarnings("DeprecatedIsStillUsed")
@Deprecated
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(FragmentManager.TAG, "Fragment " + this + " received the following in "
+ "onActivityResult(): requestCode: " + requestCode + " resultCode: "
+ resultCode + " data: " + data);
}
}
不管是 startActivityForResult() 还是 onActivityResult() 都被官方启用了,并且也提供了相应的解决策略,使用 registerForActivityResult() API。
public abstract ActivityResultLauncher<I> registerForActivityResult (ActivityResultContract<I, O> contract,
ActivityResultCallback<O> callback)
参数:
- ActivityResultContract:定义生成结果所需的输入类型以及结果的输出类型。
- ActivityResultCallback:是单一方法接口,带有 onActivityResult() 方法,可接受 ActivityResultContract 中定义的输出类型的对象。
返回:
- ActivityResultLauncher: 可用于启动活动或处理准备好的调用的启动器。
val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
// Handle the returned Uri
}
如果您有多个使用不同协定或需要单独回调的 activity 结果调用,则可以多次调用 registerForActivityResult(),以注册多个 ActivityResultLauncher 实例。每次创建 fragment 或 activity 时,都必须按照相同的顺序调用 registerForActivityResult(),才能确保将生成的结果传递给正确的回调。
虽然 registerForActivityResult() 会注册您的回调,但它不会启动另一个 activity 并发出结果请求。这些操作由返回的 ActivityResultLauncher 实例负责。
ActivityResultLauncher 提供了四个公有的方法
类型 | 方法 | 描述 |
---|---|---|
abstract ActivityResultContract<I, ?> | getContract() | Get the {@link ActivityResultContract} that was used to create this launcher. |
abstract void | unregister() | Unregisters this launcher, releasing the underlying result callback, and any references captured within it. |
abstract void | launch(I input, ActivityOptionsCompat options) | Executes an {@link ActivityResultContract}. |
void | launch(I input) | Executes an {@link ActivityResultContract}. |
如果存在输入内容,启动器会接受与 ActivityResultContract 的类型匹配的输入内容。调用 launch() 会启动生成结果的过程。当用户完成后续 activity 并返回时,系统将执行 ActivityResultCallback 中的 onActivityResult().
val getContent = registerForActivityResult(GetContent()) { uri: Uri? ->
// Handle the returned Uri
}
override fun onCreate(savedInstanceState: Bundle?) {
// ...
val selectButton = findViewById<Button>(R.id.select_button)
selectButton.setOnClickListener {
// Pass in the mime type you'd like to allow the user to select
// as the input
getContent.launch("image/*")
}
}
注意:registerForActivityResult() 必须要写在 fragment 和 activity 创建成功之前,但在 fragment 或 activity 的 Lifecycle 变为 CREATED 状态之前,您无法启动 ActivityResultLauncher。
android开发者指南:https://developer.android.google.cn