我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
我最近发现onActivityResult已弃用。我们该怎么处理呢?
有什么替代方案吗?
当前回答
如果您正在使用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)
}
}
其他回答
另一种方法是分3步完成。(考虑到你有一个startActivityForResult(0和onActivityResult()))
创建一个形式为var resultLauncher的变量:ActivityResultLauncher<Intent> 创建一个私有函数,在其中以这种基本格式初始化resultLauncher
resultLauncher=registerForActivityResult(ActivityResultContracts.StartActivityForResult()){result ->
// copy paste the code from the onActivityResult replacing resultcode to result.resultCode
if(result.resultcode==Activity.Result_OK){
val data=result.data // this data variable is of type intent and you can use it
}else{
//code if you do not get the data
}
}
使用startActivityForResult()返回行,并将其替换为resultLauncher.launch(intent)
参考: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/*")
}
}
我使用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)
添加到muntashir akon和abhijeet的答案,你可以通过在意图中传递值来修改新格式,使其像旧格式一样工作,例如:
// calling class
....
val i = Intent(this@GEBShopActivity, BarcodeScannerActivity::class.java)
when(loadedFragment){
is ShopHomeFragment -> { i.putExtra("myapp.result.code", CODE_ACTIVITY_SCAN_LIST_MAINT) }
is ShopListFragment -> { i.putExtra("myapp.result.code", CODE_ACTIVITY_SCAN_LIST_MAINT) }
is ShopItemMaintFragment -> { i.putExtra("myapp.result.code", CODE_ACTIVITY_SCAN_ITEM_MAINT) }
is ShopPriceFragment -> { i.putExtra("myapp.result.code", CODE_ACTIVITY_PRICE_CAPTURE) }
is ShopCompareFragment -> { i.putExtra("myapp.result.code", CODE_ACTIVITY_PRICE_CAPTURE) }
}
shopFragmentLauncher.launch(i)
....
// called class
....
val resultIntent = Intent()
val bundle = Bundle()
bundle.putStringArrayList("scanned_barcodes", scanned_barcodes)
bundle.putInt("scan_count", scan_count)
resultIntent.putExtras(bundle)
resultIntent.putExtra("myapp.result.code", intent.getIntExtra("myapp.result.code", 0))
setResult(Activity.RESULT_OK, resultIntent)
....
这将允许您保持类的调用相同,只需要额外的一行来添加原始调用的结果代码。还允许您创建一个可重用的启动程序实例。
dor506回答为我工作,因为我在我的大多数项目中使用BaseActivity,所以对我来说更容易在单个文件中更改代码,而不是我所有的活动。我已经写了这个代码的java版本。
BaseActivity代码:
private int requestCode = -1;
private ActivityResultLauncher<Intent> resultHandler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
registerForActivityResult();
}
private final void registerForActivityResult() {
if (shouldRegisterForActivityResult()) {
this.resultHandler = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback() {
public void onActivityResult(Object var1) {
this.onActivityResult((ActivityResult)var1);
}
public final void onActivityResult(ActivityResult result) {
Intrinsics.checkNotNullExpressionValue(result, "result");
AppActivityClass.onActivityResult(result.getData(), AppActivityClass.this.requestCode, result.getResultCode());
AppActivityClass.this.requestCode = -1;
}
});
}
}
public final void startActivityForResult(int requestCode, Intent intent) {
this.requestCode = requestCode;
if (resultHandler != null) {
resultHandler.launch(intent);
}
}
protected static void onActivityResult(Intent intent, int requestCode, int resultCode) {
}
protected Boolean shouldRegisterForActivityResult() {
return false;
}
现在在任何活动中使用这样的代码:
@Override
protected Boolean shouldRegisterForActivityResult() {
return true; // this will override the baseactivity method and we can use onactivityresult
}
private void someMethod(){
Intent i = new Intent(mContext,SomeOtherClassActivity.class);
startActivityForResult(101,i);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 101) {
if (resultCode == RESULT_OK) {
//revert from called class
}
}
}