我最近发现onActivityResult已弃用。我们该怎么处理呢?

有什么替代方案吗?


当前回答

我使用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)

其他回答

以下是我的解决方案:

在我们的项目中,我们有超过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()已经被弃用,所以使用new方法代替。

芬兰湾的科特林的例子

    fun openActivityForResult() {
        startForResult.launch(Intent(this, AnotherActivity::class.java))
    }


    val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { 
    result: ActivityResult ->
        if (result.resultCode == Activity.RESULT_OK) {
            val intent = result.data
            // Handle the Intent
            //do stuff here
        }
    }

添加到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
        }
    }
}

这就是我如何替换多个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);