我最近发现 onActivityResult 不推荐使用。我们该怎么处理呢?有没有其他办法?
onActivityResult
jc3wubiy1#
我的目标是重用当前的 startActivityForResult 方法,代码更改最少。为此,我使用onactivityresultfromlauncher方法创建了一个 Package 类和接口。
startActivityForResult
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() }}
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()
我在我的项目中使用dagger,我在需要的地方注入了 Package 器
@Injectlateinit var activityResultLauncher: ActivityResultLauncherWrapper
@Inject
lateinit var activityResultLauncher: ActivityResultLauncherWrapper
但 Package 器也可以直接示例化:
val activityResultLauncher = ActivityResultLauncherWrapper()
那你就得换衣服了 startActivityForResult 方法 launchIntentForResult . 下面是从片段调用它的示例:
launchIntentForResult
activityResultLauncher.launchIntentForResult( requireActivity(), intent, REQUEST_CODE_CONSTANT, object: ActivityResultLauncherWrapper.OnActivityResultListener { override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) { /*do something*/ } })
activityResultLauncher.launchIntentForResult(
requireActivity(),
intent,
REQUEST_CODE_CONSTANT,
object: ActivityResultLauncherWrapper.OnActivityResultListener {
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {
/*do something*/
您将在匿名对象中收到结果。你可以用 OnActivityResultListener 在片段或片段活动中,如果您实现接口并按如下方式重构当前实现:
OnActivityResultListener
class MyFragment : Fragment(), OnActivityResultListener { ...override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {/*do somthing*/} ...}
class MyFragment : Fragment(), OnActivityResultListener {
...
override fun onActivityResultFromLauncher(requestCode: Int, resultCode: Int, data: Intent?) {/*do somthing*/}
正如我们所知,kotlin类activityresultlauncherwrapper也可以在java代码中使用。我的项目中也有java类。下面是一个在片段中实现回调接口的示例:
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*/}...}
public class MyFragment extends Fragment implements OnActivityResultListener {
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*/}
我希望这有助于为您的案例构建解决方案。
zlwx9yxi2#
参考:kotlin-从图库中选择图像到目前为止我找到的最简单的动词
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/*") } }
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/*")
gwo2fgha3#
在java中,可以这样编写:
ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == AppCompatActivity.RESULT_OK) { Intent data = result.getData(); // ... } });Intent intent = new Intent( ... );startActivityForResult.launch(intent);
ActivityResultLauncher<Intent> startActivityForResult = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == AppCompatActivity.RESULT_OK) {
Intent data = result.getData();
// ...
);
Intent intent = new Intent( ... );
startActivityForResult.launch(intent);
5lhxktic4#
以下是我的解决方案:在我们的项目中,startactivityforresult(和onactivityresult)出现了20多次。我们希望尽可能少地更改代码(并继续使用请求代码),同时为将来的使用引入一个优雅的解决方案。既然我们很多开发人员都使用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 }}
abstract class BaseActivity : AppCompatActivity()
{
private var requestCode: Int = -1
private var resultHandler: ActivityResultLauncher<Intent>? = null
override fun onCreate(savedInstanceState: Bundle?)
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
下面是子活动:
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! } }}
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!
希望它能帮助别人
bkhjykvo5#
看来 onActivityResult 在超类中已弃用,但您没有提到超类名和 compileSdkVersion 这是你的问题。在java和kotlin中,只要添加 @Deprecated 因此,检查你的超类,你可能会扩展一个错误的类。当一个类被弃用时,它的所有方法也被弃用。要查看快速解决方案,请单击不推荐的方法并按 Ctrl+Q 在androidstudio中,要查看该方法的文档,应该有一个解决方案。在我的项目中使用 androidx 及api 29 as compileSdkVersion ,此方法在活动和片段中未被弃用
compileSdkVersion
@Deprecated
Ctrl+Q
androidx
ikfrs5lh6#
您可以为koltin使用扩展函数。例如:
//random utils filefun Fragment.buildGetContentRequest(function: (Uri) -> Unit): ActivityResultLauncher<String> { return this.registerForActivityResult(ActivityResultContracts.GetContent()) { function(it) }}fun Fragment.buildTakePhotoRequest(function: (Boolean) -> Unit): ActivityResultLauncher<Uri> { return this.registerForActivityResult(ActivityResultContracts.TakePicture()) { function(it) }}fun Fragment.buildSelectMultipleContentRequest(function: (MutableList<Uri>?) -> Unit): ActivityResultLauncher<String> { return this.registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { function(it) }}
//random utils file
fun Fragment.buildGetContentRequest(function: (Uri) -> Unit): ActivityResultLauncher<String> {
return this.registerForActivityResult(ActivityResultContracts.GetContent()) {
function(it)
fun Fragment.buildTakePhotoRequest(function: (Boolean) -> Unit): ActivityResultLauncher<Uri> {
return this.registerForActivityResult(ActivityResultContracts.TakePicture()) {
fun Fragment.buildSelectMultipleContentRequest(function: (MutableList<Uri>?) -> Unit): ActivityResultLauncher<String> {
return this.registerForActivityResult(ActivityResultContracts.GetMultipleContents()) {
然后在你的片段中,像这样的东西
//your actual fragment logicclass YourFragment : Fragment() { //we can assign our request in init process private val mRequestSelectFiles = buildSelectMultipleContentRequest { onFilesSelected(it) } fun onSelectFiles() { val mime = "*/*" mRequestSelectFiles.launch(mime) } fun onFilesSelected(list: MutableList<Uri>?) { //your logic }}
//your actual fragment logic
class YourFragment : Fragment() {
//we can assign our request in init process
private val mRequestSelectFiles = buildSelectMultipleContentRequest {
onFilesSelected(it)
fun onSelectFiles() {
val mime = "*/*"
mRequestSelectFiles.launch(mime)
fun onFilesSelected(list: MutableList<Uri>?) {
//your logic
ldfqzlk87#
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == Activity.RESULT_OK) { } } });
ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
new ActivityResultCallback<ActivityResult>() {
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
});
gudnpqoy8#
@muntashir-akon解决方案的kotlin版本
class BetterActivityResult<Input, Result> private constructor( caller : ActivityResultCaller, contract : ActivityResultContract<Input, Result>, var onActivityResult : ((Result) -> Unit)?,) {private val launcher : ActivityResultLauncher<Input> = caller.registerForActivityResult(contract) { onActivityResult?.invoke(it) } /** * Launch activity, same as [ActivityResultLauncher.launch] except that it * allows a callback * executed after receiving a result from the target activity. */ /** * Same as [.launch] with last parameter set to `null`. */ @JvmOverloads fun launch( input : Input, onActivityResult : ((Result) -> Unit)? = this.onActivityResult, ) { this.onActivityResult = onActivityResult launcher.launch(input) } companion object { /** * Register activity result using a [ActivityResultContract] and an in-place * activity result callback like * the default approach. You can still customise callback using [.launch]. */ fun <Input, Result> registerForActivityResult( caller : ActivityResultCaller, contract : ActivityResultContract<Input, Result>, onActivityResult : ((Result) -> Unit)?, ) : BetterActivityResult<Input, Result> { return BetterActivityResult(caller, contract, onActivityResult) } /** * Same as [.registerForActivityResult] except * the last argument is set to `null`. */ fun <Input, Result> registerForActivityResult( caller : ActivityResultCaller, contract : ActivityResultContract<Input, Result>, ) : BetterActivityResult<Input, Result> { return registerForActivityResult(caller, contract, null) } /** * Specialised method for launching new activities. */ fun registerActivityForResult( caller : ActivityResultCaller, ) : BetterActivityResult<Intent, ActivityResult> { return registerForActivityResult(caller, StartActivityForResult()) } }}
class BetterActivityResult<Input, Result> private constructor(
caller : ActivityResultCaller,
contract : ActivityResultContract<Input, Result>,
var onActivityResult : ((Result) -> Unit)?,
private val launcher : ActivityResultLauncher<Input> =
caller.registerForActivityResult(contract) { onActivityResult?.invoke(it) }
/**
* Launch activity, same as [ActivityResultLauncher.launch] except that it
* allows a callback
* executed after receiving a result from the target activity.
*/
* Same as [.launch] with last parameter set to `null`.
@JvmOverloads
fun launch(
input : Input,
onActivityResult : ((Result) -> Unit)? = this.onActivityResult,
this.onActivityResult = onActivityResult
launcher.launch(input)
companion object {
* Register activity result using a [ActivityResultContract] and an in-place
* activity result callback like
* the default approach. You can still customise callback using [.launch].
fun <Input, Result> registerForActivityResult(
onActivityResult : ((Result) -> Unit)?,
) : BetterActivityResult<Input, Result> {
return BetterActivityResult(caller, contract, onActivityResult)
* Same as [.registerForActivityResult] except
* the last argument is set to `null`.
return registerForActivityResult(caller, contract, null)
* Specialised method for launching new activities.
fun registerActivityForResult(
) : BetterActivityResult<Intent, ActivityResult> {
return registerForActivityResult(caller, StartActivityForResult())
bvk5enib9#
android 10 api 30中不推荐使用startactivityforresult和onactivityresult,现在我们有了一种使用registerforactivityresult获得结果的新方法
resultContract = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { // There are no request codes val country = result.data?.getParcelableExtra<Country>("Country") showLiveDemoDialogue(country) } }
resultContract =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
// There are no request codes
val country = result.data?.getParcelableExtra<Country>("Country")
showLiveDemoDialogue(country)
并开展活动
val intent = Intent(this, CountriesListActivity::class.java) resultContract.launch(intent)
val intent = Intent(this, CountriesListActivity::class.java)
resultContract.launch(intent)
但是你应该在呼叫launch和launch之前注册。否则,您将获得此异常
attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
kg7wmglp10#
另一种方法是分3步进行(考虑到您有一个startactivityforresult(0和onactivityresult())在表单中创建一个变量 var resultLauncher:ActivityResultLauncher<Intent> 创建一个私有函数,在该函数中以此基本格式初始化resultlauncher
var resultLauncher:ActivityResultLauncher<Intent>
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 }}
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)
startActivityForResult()
resultLauncher.launch(intent)
i34xakig11#
registerForActivityResult( ActivityResultContracts.StartActivityForResult()) { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { //... }}
registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
//...
正在从“活动”请求权限?
registerForActivityResult( ActivityResultContracts.RequestMultiplePermissions()) { //it: Map<String, Boolean>}
ActivityResultContracts.RequestMultiplePermissions()
//it: Map<String, Boolean>
使用相同的方法,但确保将这些实现放在 initialization, onAttach(), or onCreate()
initialization, onAttach(), or onCreate()
ztyzrc3y12#
基本培训可在developer.android.com上获得。以下是如何将现有代码转换为新代码的示例:老办法:
public void openSomeActivityForResult() { Intent intent = new Intent(this, SomeActivity.class); startActivityForResult(intent, 123); } @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && requestCode == 123) { doSomeOperations(); } }
public void openSomeActivityForResult() {
Intent intent = new Intent(this, SomeActivity.class);
startActivityForResult(intent, 123);
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == 123) {
doSomeOperations();
新方式(java):
// You can do the assignment inside onAttach or onCreate, i.e, before the activity is displayed ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == Activity.RESULT_OK) { // There are no request codes Intent data = result.getData(); doSomeOperations(); } } }); public void openSomeActivityForResult() { Intent intent = new Intent(this, SomeActivity.class); someActivityResultLauncher.launch(intent); }
// You can do the assignment inside onAttach or onCreate, i.e, before the activity is displayed
someActivityResultLauncher.launch(intent);
新方法(kotlin):
var resultLauncher = registerForActivityResult(StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { // There are no request codes val data: Intent? = result.data doSomeOperations() }}fun openSomeActivityForResult() { val intent = Intent(this, SomeActivity::class.java) resultLauncher.launch(intent)}
var resultLauncher = registerForActivityResult(StartActivityForResult()) { result ->
val data: Intent? = result.data
doSomeOperations()
fun openSomeActivityForResult() {
val intent = Intent(this, SomeActivity::class.java)
编辑一个更好的方法是使它更加通用,以便我们可以重用它。下面的代码片段用于我的一个项目中,但请注意,它没有经过良好测试,可能无法涵盖所有情况。betteractivityresult.java
import android.content.Intent;import androidx.activity.result.ActivityResult;import androidx.activity.result.ActivityResultCaller;import androidx.activity.result.ActivityResultLauncher;import androidx.activity.result.contract.ActivityResultContract;import androidx.activity.result.contract.ActivityResultContracts;import androidx.annotation.NonNull;import androidx.annotation.Nullable;public class BetterActivityResult<Input, Result> { /** * Register activity result using a {@link ActivityResultContract} and an in-place activity result callback like * the default approach. You can still customise callback using {@link #launch(Object, OnActivityResult)}. */ @NonNull public static <Input, Result> BetterActivityResult<Input, Result> registerForActivityResult( @NonNull ActivityResultCaller caller, @NonNull ActivityResultContract<Input, Result> contract, @Nullable OnActivityResult<Result> onActivityResult) { return new BetterActivityResult<>(caller, contract, onActivityResult); } /** * Same as {@link #registerForActivityResult(ActivityResultCaller, ActivityResultContract, OnActivityResult)} except * the last argument is set to {@code null}. */ @NonNull public static <Input, Result> BetterActivityResult<Input, Result> registerForActivityResult( @NonNull ActivityResultCaller caller, @NonNull ActivityResultContract<Input, Result> contract) { return registerForActivityResult(caller, contract, null); } /** * Specialised method for launching new activities. */ @NonNull public static BetterActivityResult<Intent, ActivityResult> registerActivityForResult( @NonNull ActivityResultCaller caller) { return registerForActivityResult(caller, new ActivityResultContracts.StartActivityForResult()); } /** * Callback interface */ public interface OnActivityResult<O> { /** * Called after receiving a result from the target activity */ void onActivityResult(O result); } private final ActivityResultLauncher<Input> launcher; @Nullable private OnActivityResult<Result> onActivityResult; private BetterActivityResult(@NonNull ActivityResultCaller caller, @NonNull ActivityResultContract<Input, Result> contract, @Nullable OnActivityResult<Result> onActivityResult) { this.onActivityResult = onActivityResult; this.launcher = caller.registerForActivityResult(contract, this::callOnActivityResult); } public void setOnActivityResult(@Nullable OnActivityResult<Result> onActivityResult) { this.onActivityResult = onActivityResult; } /** * Launch activity, same as {@link ActivityResultLauncher#launch(Object)} except that it allows a callback * executed after receiving a result from the target activity. */ public void launch(Input input, @Nullable OnActivityResult<Result> onActivityResult) { if (onActivityResult != null) { this.onActivityResult = onActivityResult; } launcher.launch(input); } /** * Same as {@link #launch(Object, OnActivityResult)} with last parameter set to {@code null}. */ public void launch(Input input) { launch(input, this.onActivityResult); } private void callOnActivityResult(Result result) { if (onActivityResult != null) onActivityResult.onActivityResult(result); }}
import android.content.Intent;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCaller;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class BetterActivityResult<Input, Result> {
* Register activity result using a {@link ActivityResultContract} and an in-place activity result callback like
* the default approach. You can still customise callback using {@link #launch(Object, OnActivityResult)}.
@NonNull
public static <Input, Result> BetterActivityResult<Input, Result> registerForActivityResult(
@NonNull ActivityResultCaller caller,
@NonNull ActivityResultContract<Input, Result> contract,
@Nullable OnActivityResult<Result> onActivityResult) {
return new BetterActivityResult<>(caller, contract, onActivityResult);
* Same as {@link #registerForActivityResult(ActivityResultCaller, ActivityResultContract, OnActivityResult)} except
* the last argument is set to {@code null}.
@NonNull ActivityResultContract<Input, Result> contract) {
return registerForActivityResult(caller, contract, null);
public static BetterActivityResult<Intent, ActivityResult> registerActivityForResult(
@NonNull ActivityResultCaller caller) {
return registerForActivityResult(caller, new ActivityResultContracts.StartActivityForResult());
* Callback interface
public interface OnActivityResult<O> {
* Called after receiving a result from the target activity
void onActivityResult(O result);
private final ActivityResultLauncher<Input> launcher;
@Nullable
private OnActivityResult<Result> onActivityResult;
private BetterActivityResult(@NonNull ActivityResultCaller caller,
this.onActivityResult = onActivityResult;
this.launcher = caller.registerForActivityResult(contract, this::callOnActivityResult);
public void setOnActivityResult(@Nullable OnActivityResult<Result> onActivityResult) {
* Launch activity, same as {@link ActivityResultLauncher#launch(Object)} except that it allows a callback
public void launch(Input input, @Nullable OnActivityResult<Result> onActivityResult) {
if (onActivityResult != null) {
launcher.launch(input);
* Same as {@link #launch(Object, OnActivityResult)} with last parameter set to {@code null}.
public void launch(Input input) {
launch(input, this.onActivityResult);
private void callOnActivityResult(Result result) {
if (onActivityResult != null) onActivityResult.onActivityResult(result);
使用上述方法,您仍然必须在启动活动或片段附件之前或期间注册它。一旦定义,它就可以在活动或片段中重用。例如,如果需要在大多数活动中启动新活动,可以定义 BaseActivity 并注册一个新的 BetterActivityResult 这样地:baseactivity.java
BaseActivity
BetterActivityResult
public class BaseActivity extends AppCompatActivity { protected final BetterActivityResult<Intent, ActivityResult> activityLauncher = BetterActivityResult.registerActivityForResult(this);}
public class BaseActivity extends AppCompatActivity {
protected final BetterActivityResult<Intent, ActivityResult> activityLauncher = BetterActivityResult.registerActivityForResult(this);
之后,您只需从任何子活动启动活动,如下所示:
public void openSomeActivityForResult() { Intent intent = new Intent(this, SomeActivity.class); activityLauncher.launch(intent, result -> { if (result.getResultCode() == Activity.RESULT_OK) { // There are no request codes Intent data = result.getData(); doSomeOperations(); } }) }
activityLauncher.launch(intent, result -> {
})
因为您可以将回调函数与 Intent ,您可以将其重新用于任何活动。同样,您也可以使用其他两个构造函数使用其他活动契约。
Intent
mm9b1k5b13#
从现在起,, startActivityForResult() 已弃用,请使用新方法。Kotlin示例
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 } }
fun openActivityForResult() {
startForResult.launch(Intent(this, AnotherActivity::class.java))
val startForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
result: ActivityResult ->
val intent = result.data
// Handle the Intent
//do stuff here
t2a7ltrp14#
在Kotlin,我更改了代码
startActivityForResult(intent, Constants.MY_CODE_REQUEST)
和
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK) { when (requestCode) { Constants.MY_CODE_REQUEST -> { ...}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
Constants.MY_CODE_REQUEST -> {
到
registerForActivityResult(StartActivityForResult()) { result -> onActivityResult(Constants.MY_CODE_REQUEST, result)}.launch(intent)
registerForActivityResult(StartActivityForResult()) { result ->
onActivityResult(Constants.MY_CODE_REQUEST, result)
}.launch(intent)
private fun onActivityResult(requestCode: Int, result: ActivityResult) { if(result.resultCode == Activity.RESULT_OK) { val intent = result.data when (requestCode) { Constants.MY_CODE_REQUEST -> { ...
private fun onActivityResult(requestCode: Int, result: ActivityResult) {
if(result.resultCode == Activity.RESULT_OK) {
我希望它对你有用D
jfgube3f15#
新方法是: registerForActivityResult 优点:新的方法是降低当我们从片段或另一个活动调用活动时所面临的复杂性轻松请求任何许可并获得回拨在Kotlin:
registerForActivityResult
var launchSomeActivity = registerForActivityResult(StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { val data: Intent? = result.data // your operation... }}fun openYourActivity() { val intent = Intent(this, SomeActivity::class.java) launchSomeActivity.launch(intent)}
var launchSomeActivity = registerForActivityResult(StartActivityForResult()) { result ->
// your operation...
fun openYourActivity() {
launchSomeActivity.launch(intent)
在java中:
// Create lanucher variable inside onAttach or onCreate or global ActivityResultLauncher<Intent> launchSomeActivity = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == Activity.RESULT_OK) { Intent data = result.getData(); // your operation.... } } }); public void openYourActivity() { Intent intent = new Intent(this, SomeActivity.class); launchSomeActivity.launch(intent); }
// Create lanucher variable inside onAttach or onCreate or global
ActivityResultLauncher<Intent> launchSomeActivity = registerForActivityResult(
// your operation....
public void openYourActivity() {
launchSomeActivity.launch(intent);
16条答案
按热度按时间jc3wubiy1#
我的目标是重用当前的
startActivityForResult
方法,代码更改最少。为此,我使用onactivityresultfromlauncher方法创建了一个 Package 类和接口。我在我的项目中使用dagger,我在需要的地方注入了 Package 器
但 Package 器也可以直接示例化:
那你就得换衣服了
startActivityForResult
方法launchIntentForResult
. 下面是从片段调用它的示例:您将在匿名对象中收到结果。你可以用
OnActivityResultListener
在片段或片段活动中,如果您实现接口并按如下方式重构当前实现:正如我们所知,kotlin类activityresultlauncherwrapper也可以在java代码中使用。我的项目中也有java类。下面是一个在片段中实现回调接口的示例:
我希望这有助于为您的案例构建解决方案。
zlwx9yxi2#
参考:kotlin-从图库中选择图像
到目前为止我找到的最简单的动词
gwo2fgha3#
在java中,可以这样编写:
5lhxktic4#
以下是我的解决方案:
在我们的项目中,startactivityforresult(和onactivityresult)出现了20多次。
我们希望尽可能少地更改代码(并继续使用请求代码),同时为将来的使用引入一个优雅的解决方案。
既然我们很多开发人员都使用baseactivity概念,为什么不利用它呢?
以下是基本活动:
下面是子活动:
希望它能帮助别人
bkhjykvo5#
看来
onActivityResult
在超类中已弃用,但您没有提到超类名和compileSdkVersion
这是你的问题。在java和kotlin中,只要添加
@Deprecated
因此,检查你的超类,你可能会扩展一个错误的类。当一个类被弃用时,它的所有方法也被弃用。
要查看快速解决方案,请单击不推荐的方法并按
Ctrl+Q
在androidstudio中,要查看该方法的文档,应该有一个解决方案。在我的项目中使用
androidx
及api 29 ascompileSdkVersion
,此方法在活动和片段中未被弃用ikfrs5lh6#
您可以为koltin使用扩展函数。例如:
然后在你的片段中,像这样的东西
ldfqzlk87#
gudnpqoy8#
@muntashir-akon解决方案的kotlin版本
bvk5enib9#
android 10 api 30中不推荐使用startactivityforresult和onactivityresult,现在我们有了一种使用registerforactivityresult获得结果的新方法
并开展活动
但是你应该在呼叫launch和launch之前注册。否则,您将获得此异常
kg7wmglp10#
另一种方法是分3步进行(考虑到您有一个startactivityforresult(0和onactivityresult())
在表单中创建一个变量
var resultLauncher:ActivityResultLauncher<Intent>
创建一个私有函数,在该函数中以此基本格式初始化resultlauncher去排队
startActivityForResult()
并将其替换为线路resultLauncher.launch(intent)
i34xakig11#
startactivityforresult和requestmultiplepermissions from activity和fragment的registerforactivityresult的简单示例[在kotlin中]
正在请求活动以获取活动的结果
查看activityresult
正在从“活动”请求权限?
来自碎片?
使用相同的方法,但确保将这些实现放在
initialization, onAttach(), or onCreate()
ztyzrc3y12#
基本培训可在developer.android.com上获得。
以下是如何将现有代码转换为新代码的示例:
老办法:
新方式(java):
新方法(kotlin):
编辑一个更好的方法是使它更加通用,以便我们可以重用它。下面的代码片段用于我的一个项目中,但请注意,它没有经过良好测试,可能无法涵盖所有情况。
betteractivityresult.java
使用上述方法,您仍然必须在启动活动或片段附件之前或期间注册它。一旦定义,它就可以在活动或片段中重用。例如,如果需要在大多数活动中启动新活动,可以定义
BaseActivity
并注册一个新的BetterActivityResult
这样地:baseactivity.java
之后,您只需从任何子活动启动活动,如下所示:
因为您可以将回调函数与
Intent
,您可以将其重新用于任何活动。同样,您也可以使用其他两个构造函数使用其他活动契约。
mm9b1k5b13#
从现在起,,
startActivityForResult()
已弃用,请使用新方法。Kotlin示例
t2a7ltrp14#
在Kotlin,我更改了代码
和
到
和
我希望它对你有用D
jfgube3f15#
新方法是:
registerForActivityResult
优点:新的方法是降低当我们从片段或另一个活动调用活动时所面临的复杂性
轻松请求任何许可并获得回拨
在Kotlin:
在java中: