launchMode带来的onActivityResult失效问题

本文探讨了不同launchMode设置下Activity之间的跳转及数据回传问题,特别是在singleTask和singleInstance模式下可能导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  项目开发中遇到一个问题,由ActivityA跳转到ActivityB时,如果ActivityB设置了launchMode,并且B界面finish时需要返回给ActivityA一些数据,这时候ActivityA对于ActivityB的onActivityResult()方法可能会出现一些问题。下面写一个简单的小demo来验证一下。
  A中有一个按钮进行界面跳转到B,

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(A.this,B.class);
                startActivityForResult(intent,REQUST_CODE);
            }
        });

  B中按钮finish,返回A界面。

finish.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("test", "data from B");
                setResult(RESULT_OK,intent);
                finish();
            }
        });

  最后在A中进行处理,

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode==RESULT_OK){
            String result=data.getStringExtra("test");
            Toast.makeText(getApplicationContext(),"RESULT_OK  "+result,Toast.LENGTH_SHORT).show();
        }

        if (resultCode==RESULT_CANCELED){
            Toast.makeText(getApplicationContext(),"RESULT_CANCELED",Toast.LENGTH_SHORT).show();
        }
    }

  关于launchMode就不详细讲解了,这里简单说一下。
standard:默认的启动模式,每次启动都会在当前栈中重新生成一个新的 Activity实例。
singleTop:启动时先去检查栈顶是不是当前Activity实例,是的则直接使用,不 是的就重新创建。
singleTask:保证当前栈中只有自己的一个实例,通常的做法是,如果在栈中发现了自己的Activity实例,就将这个实例之上的其他Activity实例统统赶走,使自己成为栈顶。
singleInstance:这个模式最霸道,会重新建一个栈,把自己的Activity实例放进去,并且不会再放入其他Activity实例。

  先测试一下standard模式,清单文件ActivityB中加入android:launchMode="standard",断点调试。点击A中按钮,跳转到B,点击B中按钮,进入断点,如下图所示,这是A成功收到B返回过来的数据,standard模式启动Activity对onActivityResult没有影响。standard模式

  接下来以同样的方式测试singleTop模式,测试结果与standard模式一样,这里不再赘述。
  接着将B的启动模式改为singleTask继续断点测试,这次结果就比较出人意料,与之前有很大区别。当我点击A中跳转按钮时,就直接进入了onActivityResult中的断点,注意这里进入断点的时间,并不是点击B中finish按钮后才进入断点。这里我就产生了一个疑惑,当我点击按钮去进行跳转按钮之后,是不是压根就没有进入B界面。为了验证一下这个问题,我在B界面的onCreate()方法上也打上断点,来看一下代码的执行顺序。这次,当我点击A中按钮后。首先执行的依然是A中的onActivityResult方法,那么此时的resultCode是多少呢?请注意看下图,

singleTask模式
  可以看到此时的resultCode是一个值为0的常量,RESULT_CANCELED,所以这样是完全没有办法接收数据的,也就是在调用startActivityForResult()之后就直接调用了onActivityResult(),并给出了一个值为0的结果码。至于具体原因,暂时还没有想到比较合理的解释,哪位大牛知道原因的和小弟说道说道。
  最后来测试一下singleInstance模式,发现和singleTask模式一样。
  所以,如果当你要跳转的Activity的启动模式为singleTask或者singleInstance时,会导致跳转前Activity无法收到跳转后Activity返回的数据,在这里要注意一下。

package com.example.cameraapplication; import android.app.ComponentCaller; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import androidx.activity.EdgeToEdge; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.FileProvider; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; public class MainActivity extends AppCompatActivity { private static final int TAKE_PHOTO = 1; private ImageView picture; private Uri imageUri; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); Button take_pic = (Button) findViewById(R.id.take_photo); picture = (ImageView) findViewById(R.id.picture); take_pic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { File outputimage = new File(getExternalCacheDir(),"outputimage.jpg"); try { if(outputimage.exists()){ outputimage.delete(); } outputimage.createNewFile(); } catch (IOException e) { throw new RuntimeException(e); } if(Build.VERSION.SDK_INT >= 24){ imageUri = FileProvider.getUriForFile(MainActivity.this,"com.example.cameraapplication.provider",outputimage); } else { imageUri = Uri.fromFile(outputimage); } Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri); startActivityForResult(intent,TAKE_PHOTO); Log.d("cmap", "take_photo"); } }); } @Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data, @NonNull ComponentCaller caller) { //super.onActivityResult(requestCode, resultCode, data, caller); Log.d("cmap", "onActivityResult"); if(requestCode == TAKE_PHOTO){ try { Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri)); Log.d("cmap", "get_photo"); picture.setImageBitmap(bitmap); Log.d("cmap", "set_photo"); } catch (FileNotFoundException e) { throw new RuntimeException(e); } } } }onActivityResult方法不执行的原因
最新发布
07-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值