我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
当前回答
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
}
}
});
其他回答
以下是我的解决方案:
在我们的项目中,我们有超过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!
}
}
}
希望它能帮助到别人
下面的代码在Kotlin片段中工作,用于检查蓝牙权限。年- 2022年
val intent = intent (BluetoothAdapter.ACTION_REQUEST_ENABLE)
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// There are no request codes
val data: Intent? = result.data
bluetoothAdapter.enable()
Toast.makeText(context, "Permission Granted: ", Toast.LENGTH_SHORT).show()
dynamicButton()
}
else{Toast.makeText(context, "You have to enable bluetooth to use this app.", Toast.LENGTH_SHORT).show()}
}.launch(intent)
我使用kotlin扩展,使它非常简单。在你的扩展中添加以下扩展功能。kt文件:
fun AppCompatActivity.startForResult(intent: Intent,
onResult: (resultCode: Int, data: Intent?) -> Unit
) {
this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {result ->
onResult(result.resultCode, result.data)
}.launch(intent)
}
现在,在继承AppCompatActivity的任何活动中,你可以使用下面的简单代码:
val i = Intent(this, TargetActivity::class.java)
startForResult(i) { resultCode, data ->
//put your code here like:
if (resultCode == RESULT_OK) {
//your code here...
}
}
}
更新 上述实现可能导致以下异常: java.lang.IllegalStateException: LifecycleOwner xxxx正在尝试注册,而当前状态为恢复。生命周期所有者必须在启动之前调用寄存器。
因此,registerForActivityResult应该提前调用,例如在onCreate之前。这是另一种解决方案。
在你的扩展中添加以下扩展功能。kt文件:
fun AppCompatActivity.registerForResult(onResult: (resultCode: Int, data: Intent?) -> Unit):
ActivityResultLauncher<Intent> {
return this.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
onResult(result.resultCode, result.data)
}
}
现在,在继承AppCompatActivity的任何活动中,你可以使用下面的简单代码:
为每个需要结果的操作定义一个类成员变量
private val myActionResult = registerForResult { resultCode, data ->
//put your code here like:
if (resultCode == RESULT_OK) {
//your code here...
}
}
}
启动动作
val i = Intent(this, TargetActivity::class.java)
myActionResult.launch(i)
参考: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/*")
}
}
在替换已弃用的方法startActivityForResult(…)时,需要遵循4个简单的步骤。
In place of overridden method onActivityResult(..) - ActivityResultLauncher<Intent> activityResultLaunch = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == 123) { // ToDo : Do your stuff... } else if(result.getResultCode() == 321) { // ToDo : Do your stuff... } } });
对于多个自定义请求,将条件附加为
if (result.getResultCode() == 123) {
..
} else if(result.getResultCode() == 131){
..
} // so on..
Imports : import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; In place of startActivityForResult(intent, 123), use Intent intent = new Intent(this, SampleActivity.class); activityResultLaunch.launch(intent); In SampleActivity.java class, while returning back to source activity, code will remain the same like - Intent intent = new Intent(); setResult(123, intent); finish();
编码快乐!:)