我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
当前回答
以下是我的解决方案:
在我们的项目中,我们有超过20次的startActivityForResult(和onActivityResult)。
我们希望尽可能少地更改代码(并继续使用请求代码),同时引入一个优雅的解决方案以供将来使用。
既然我们很多开发人员都使用BaseActivity概念——为什么不利用它呢?
下面是BaseActivity:
abstract class BaseActivity : AppCompatActivity()
{
private var requestCode: Int = -1
private var resultHandler: ActivityResultLauncher<Intent>? = null
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
registerForActivityResult()
}
private fun registerForActivityResult()
{
if (shouldRegisterForActivityResult())
{
resultHandler = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
onActivityResult(result.data, requestCode, result.resultCode)
this.requestCode = -1
}
}
}
fun startActivityForResult(requestCode: Int, intent: Intent)
{
this.requestCode = requestCode
resultHandler?.launch(intent)
}
protected open fun onActivityResult(data: Intent?, requestCode: Int, resultCode: Int)
{
// For sub activities
}
protected open fun shouldRegisterForActivityResult(): Boolean
{
// Sub activities that need the onActivityResult "mechanism", should override this and return true
return false
}
}
这是SubActivity:
class SubActivity : BaseActivity()
{
companion object
{
private const val SOME_REQUEST_CODE = 300
}
private fun testActivityResult()
{
val intent = Intent(this, OtherActivity::class.java)
startActivityForResult(SOME_REQUEST_CODE, intent)
}
override fun shouldRegisterForActivityResult(): Boolean
{
return true
}
override fun onActivityResult(data: Intent?, requestCode: Int, resultCode: Int)
{
if (requestCode == SOME_REQUEST_CODE)
{
// Yes!
}
}
}
希望它能帮助到别人
其他回答
结合上面的答案,我有一个与旧方法兼容的方法startActivityForResult()保持使用requestCode而不改变旧的代码结构:
ActivityLauncher.class
public class ActivityLauncher {
private final ActivityResultLauncher<Intent> launcher;
private ActivityResultCallback<ActivityResult> activityResultCallback;
private ActivityLauncher(@NonNull ActivityResultCaller caller,
@NonNull ActivityResultContract<Intent, ActivityResult> contract,
@Nullable ActivityResultCallback<ActivityResult> activityResultCallback) {
this.activityResultCallback = activityResultCallback;
this.launcher = caller.registerForActivityResult(contract, this::onActivityResult);
}
public static ActivityLauncher registerActivityForResult(
@NonNull ActivityResultCaller caller) {
return new ActivityLauncher(caller, new ActivityResultContracts.StartActivityForResult(), null);
}
public void launch(Intent intent, @Nullable ActivityResultCallback<ActivityResult> activityResultCallback) {
if (activityResultCallback != null) {
this.activityResultCallback = activityResultCallback;
}
launcher.launch(intent);
}
private void onActivityResult(ActivityResult result) {
if (activityResultCallback != null) activityResultCallback.onActivityResult(result);
}
public interface OnActivityResult {
void onActivityResultCallback(int requestCode, int resultCode, Intent data);
}
}
在BaseActivity.java中代码
private final ActivityLauncher activityLauncher = ActivityLauncher.registerActivityForResult(this);
public void startActivityForResult(Intent intent, int requestCode, ActivityLauncher.OnActivityResult onActivityResult) {
activityLauncher.launch(intent, result -> onActivityResult.onActivityResultCallback(requestCode, result.getResultCode(), result.getData()));
}
最后在每个扩展BaseActivity的Activity中,实现ActivityLauncher。将覆盖函数“OnActivityResult”的名称改为“onActivityResultCallback”。还记得删除super.onActivityResult()
如何使用:startActivityForResult(intent, requestCode, this)
参考:Kotlin -从图库中选择图像
迄今为止我发现的最简单的Alernative
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.id.activity_main)
var ivPhoto = findViewById<ImageView>(R.id.ivPhoto)
var btnChoosePhoto = findViewById<Button>(R.id.btnChoosePhoto)
val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
ivPhoto.setImageURI(uri) // Handle the returned Uri
}
btnChoose.setOnClickListener {
getContent.launch("image/*")
}
}
一个简单的例子:registerForActivityResult和requestmultiplepermission from Activity和Fragment
请求活动以获得活动的结果
registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
//...
}
}
检查ActivityResult
向活动请求许可?
registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) {
//it: Map<String, Boolean>
}
从片段?
使用相同的方法,但确保将这些实现放在初始化中,onAttach()或onCreate()
如果你像这样实现你的base Activity,你可以继续使用旧的startActivityForResult。 唯一的限制是你必须使用setResult(result, intent)在你的活动中设置结果。 关键是让结果将请求代码带回结果使用者。
public class MyBaseActivity extends AppCompatActivity {
private ActivityResultLauncher<Intent> activityLauncher;
protected static String ACTIVITY_REQUEST_CODE = "my.activity.request.code";
protected _originalIntent;
public void launchActivityForResult(Intent intent, int requestCode){
intent.putExtra(UGM_ACTIVITY_REQUEST_CODE, requestCode);
activityLauncher.launch(intent);
}
//
//In order to be signature compatible for the rest of derived activities,
//we will override the deprecated method with our own implementation!
//
@SuppressWarnings( "deprecation" )
public void startActivityForResult(Intent intent, int requestCode){
launchActivityForResult(intent, requestCode);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_originalIntent = getIntent();
//set the default result
setResult(Activity.RESULT_OK, _originalIntent);
activityLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
Intent intent = result.getData();
int requestCode = intent.getIntExtra(ACTIVITY_REQUEST_CODE, -1);
MyBaseActivity.this.onActivityResult(requestCode, result.getResultCode(), intent);
}
});
}
}
如果您正在使用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)
}
}