我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
当前回答
这就是我如何替换多个requestCodes(把这段代码放在你的活动中):
ActivityResultLauncher<Intent> launchCameraActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
Bitmap photoBitmap;
if(data != null && data.getExtras() != null){
photoBitmap = (Bitmap) data.getExtras().get("data");
if (photoBitmap != null) {
dataModel.setPhoto(ImageUtil.convert(photoBitmap));
imageTaken.setVisibility(View.VISIBLE);
imageTaken.setImageBitmap(photoBitmap);
}
}
}
}
});
ActivityResultLauncher<Intent> launchCameraAndGalleryActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
Uri imageUri;
if (data != null) {
imageUri = data.getData();
InputStream imageStream;
try {
imageStream = getContentResolver().openInputStream(imageUri);
Bitmap photoBitmap = BitmapFactory.decodeStream(imageStream);
dataModel.setOtherImage(ImageUtil.convert(photoBitmap));
documentImageTaken.setVisibility(View.VISIBLE);
documentImageTaken.setImageBitmap(photoBitmap);
}catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
});
我是这样开展活动的:
Intent photoIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
launchCameraAndGalleryActivity.launch(photoIntent );
Intent galleryIntent= new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
launchCameraActivity.launch(galleryIntent);
其他回答
我的目标是用最少的代码更改重用startActivityForResult方法的当前实现。为此,我使用onActivityResultFromLauncher方法创建了一个包装器类和接口。
interface ActivityResultLauncherWrapper {
fun launchIntentForResult(activity: FragmentActivity, intent: Intent, requestCode: Int, callBack: OnActivityResultListener)
fun unregister()
interface OnActivityResultListener {
fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?)
}
}
class ActivityResultLauncherWrapperImpl : ActivityResultLauncherWrapper {
private var weakLauncher: WeakReference<ActivityResultLauncher<Intent>>? = null
override fun launchIntentForResult(
activity: FragmentActivity,
intent: Intent,
requestCode: Int,
callBack: ActivityResultLauncherWrapper.OnActivityResultListener
) {
weakLauncher = WeakReference(
activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
callBack.onActivityResultFromLauncher(requestCode, result.resultCode, result.data)
}
)
weakLauncher?.get()?.launch(intent)
}
override fun unregister() {
weakLauncher?.get()?.unregister()
}
}
我在我的项目中使用匕首,我在需要的地方注入了包装器
@Inject
lateinit var activityResultLauncher: ActivityResultLauncherWrapper
但是包装器也可以直接实例化:
val activityResultLauncher = ActivityResultLauncherWrapper()
然后你必须用launchIntentForResult改变startActivityForResult方法。下面是一个从片段中调用它的例子:
activityResultLauncher.launchIntentForResult(
requireActivity(),
intent,
REQUEST_CODE_CONSTANT,
object: ActivityResultLauncherWrapper.OnActivityResultListener {
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {
/*do something*/
}
}
)
您将在匿名对象中收到结果。 你可以在Fragment或FragmentActivity中使用OnActivityResultListener,如果你实现了接口,并像这样重构当前的实现:
class MyFragment : Fragment(), OnActivityResultListener {
...
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {/*do somthing*/}
...
}
正如我们所知,Kotlin类ActivityResultLauncherWrapper也可以在java代码中使用。在我的项目中也有java类。这里有一个在Fragment中实现回调接口的例子:
public class MyFragment extends Fragment implements OnActivityResultListener {
...
@Inject
ActivityResultLauncherWrapper activityResultLauncher;
//ActivityResultLauncherWrapper activityResultLauncher = new ActivityResultLauncherWrapper()
...
public void launnchActivity(@NotNull Intent intent) {
activityResultLauncher.launchIntentForResult(requireActivity(), intent, REQUEST_CODE_CONSTANT, this);
}
...
@Override
public void onActivityResultFromLauncher(int requestCode, int resultCode, Intent data) {/*do somthing*/}
...
}
我希望这有助于为您的案例构建解决方案。
Kotlin版本的@Muntashir阿肯解决方案
class BetterActivityResult<Input, Result> private constructor(
caller : ActivityResultCaller,
contract : ActivityResultContract<Input, Result>,
var onActivityResult : ((Result) -> Unit)?,
) {
private val launcher : ActivityResultLauncher<Input> =
caller.registerForActivityResult(contract) { onActivityResult?.invoke(it) }
/**
* Launch activity, same as [ActivityResultLauncher.launch] except that it
* allows a callback
* executed after receiving a result from the target activity.
*/
/**
* Same as [.launch] with last parameter set to `null`.
*/
@JvmOverloads
fun launch(
input : Input,
onActivityResult : ((Result) -> Unit)? = this.onActivityResult,
) {
this.onActivityResult = onActivityResult
launcher.launch(input)
}
companion object {
/**
* Register activity result using a [ActivityResultContract] and an in-place
* activity result callback like
* the default approach. You can still customise callback using [.launch].
*/
fun <Input, Result> registerForActivityResult(
caller : ActivityResultCaller,
contract : ActivityResultContract<Input, Result>,
onActivityResult : ((Result) -> Unit)?,
) : BetterActivityResult<Input, Result> {
return BetterActivityResult(caller, contract, onActivityResult)
}
/**
* Same as [.registerForActivityResult] except
* the last argument is set to `null`.
*/
fun <Input, Result> registerForActivityResult(
caller : ActivityResultCaller,
contract : ActivityResultContract<Input, Result>,
) : BetterActivityResult<Input, Result> {
return registerForActivityResult(caller, contract, null)
}
/**
* Specialised method for launching new activities.
*/
fun registerActivityForResult(
caller : ActivityResultCaller,
) : BetterActivityResult<Intent, ActivityResult> {
return registerForActivityResult(caller, StartActivityForResult())
}
}
}
如果您正在使用SMS同意API,则使用以下代码(Kotlin):
resultLauncher.launch( consentIntent
)
var resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// There are no request codes
// val data: Intent? = result.data
val message = result.data?.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
getOtpFromMessage(message)
}
}
startActivityForResult和onActivityResult在android 10 API 30中已弃用,现在我们有了一种新的方法来使用registerForActivityResult来获得结果
resultContract =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// There are no request codes
val country = result.data?.getParcelableExtra<Country>("Country")
showLiveDemoDialogue(country)
}
}
并启动活动
val intent = Intent(this, CountriesListActivity::class.java)
resultContract.launch(intent)
但你应该在呼叫发射前注册然后发射到你想去的任何地方。 否则,您将得到这个异常
attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
这就是我如何替换多个requestCodes(把这段代码放在你的活动中):
ActivityResultLauncher<Intent> launchCameraActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
Bitmap photoBitmap;
if(data != null && data.getExtras() != null){
photoBitmap = (Bitmap) data.getExtras().get("data");
if (photoBitmap != null) {
dataModel.setPhoto(ImageUtil.convert(photoBitmap));
imageTaken.setVisibility(View.VISIBLE);
imageTaken.setImageBitmap(photoBitmap);
}
}
}
}
});
ActivityResultLauncher<Intent> launchCameraAndGalleryActivity = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
Uri imageUri;
if (data != null) {
imageUri = data.getData();
InputStream imageStream;
try {
imageStream = getContentResolver().openInputStream(imageUri);
Bitmap photoBitmap = BitmapFactory.decodeStream(imageStream);
dataModel.setOtherImage(ImageUtil.convert(photoBitmap));
documentImageTaken.setVisibility(View.VISIBLE);
documentImageTaken.setImageBitmap(photoBitmap);
}catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
});
我是这样开展活动的:
Intent photoIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
launchCameraAndGalleryActivity.launch(photoIntent );
Intent galleryIntent= new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
launchCameraActivity.launch(galleryIntent);