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

有什么替代方案吗?


当前回答

一个简单的例子: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()

其他回答

分享我找到的解决方法

首先,使用registerForActivityResult为结果注册这个活动 这将返回一个类型为ActivityResultLauncher<Intent!> 像这样,

private val getResult =
        registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) {
            if (it.resultCode == Activity.RESULT_OK) {
                val value = it.data?.getStringExtra("input")
            }
        }

现在,无论我们想在哪里启动result活动我们都可以使用getresult。launch(intent)

我的目标是用最少的代码更改重用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*/}
...
}

我希望这有助于为您的案例构建解决方案。

从现在开始,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
        }
    }

我想出了如何从Kotlin的片段中正确地做到这一点,以捕获图像并处理返回的位图。在其他情况下也是一样的。

首先,您必须注册片段以侦听活动结果。这必须在初始化片段之前完成,这意味着创建一个成员变量,而不是在onCreate函数中初始化。

class DummyFragment : Fragment() {

  //registering fragment for camera listener
  private val takePhoto = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
  ) {
    if (it.resultCode == Activity.RESULT_OK) {
      val imageBitmap = it.data?.extras?.get("data") as Bitmap
      // do your thing with the obtained bitmap
    }
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  }

}

然后,像你通常做的那样调用摄像机意图。并使用上面创建的变量来启动意图。

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  someRandomButton.setOnClickListener {
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    takePhoto.launch(takePictureIntent)
  }
}

结合上面的答案,我有一个与旧方法兼容的方法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)