使用startActivityForResult一定要注意Activity的启动模式。如果不注意执行startActivityForResult,没等到被调用的 Activity 返回,onActivityResult() 就被执行了。将lanchMode设置为标准模式就好了。
看api的注释:For example, if the activity you
* are launching uses the singleTask launch mode, it will not run in your
* task and thus you will immediately receive a cancel result.
三个Activity连传intent案例
分享一个我在实际开发中遇到的例子。
问题描述如下:
要求最一个商家注册功能的实现,里面有个服务选项,这个服务选项是有两级分类组成,没个用户只能选择一级分类的下面的二级分类,不可以跨组选分类。选择后肯定要将数据显示到注册页面上。
我的实现方法是这样的:设注册页面的Activity为A,一级分类的Activity为B,二级分类的Activity为C。
主要看A中Intent启动的是B,如何收到C的数据的!其他数据可以忽略,可以根据项目中的需要,传递。
A:
public class A_Activity extends Activity {
private TextView mTv_a;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.a_activity);
mTv_a = (TextView) findViewById(R.id.tv_a);
mTv_a.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(A_Activity.this, B_Activity.class); // 指定启动B
intent.putExtra("DATA1", "从A中传入的数据");
startActivityForResult(intent, 1);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
// TODO Auto-generated method stub
if(requestCode == 1 && resultCode == 1){
Log.d("TAG",intent.getStringExtra("DATA3"));
}
super.onActivityResult(requestCode, resultCode, intent);
}
}
B:
public class B_Activity extends Activity {
private TextView mTv_b;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.b_activity);
mTv_b = (TextView) findViewById(R.id.tv_b);
mTv_b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(B_Activity.this,
C_Activity.class);
intent.putExtra("DATA2", "从B中传入的数据");
startActivityForResult(intent, 2);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
// TODO Auto-generated method stub
if(requestCode == 2 && resultCode == 2){
B_Activity.this.setResult(1, intent);
B_Activity.this.finish();
}
super.onActivityResult(requestCode, resultCode, intent);
}
}
C:
public class C_Activity extends Activity {
private TextView mTv_c;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.c_activity);
mTv_c = (TextView) findViewById(R.id.tv_c);
mTv_c.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = getIntent();
intent.putExtra("DATA3", "从C中传入的数据");
C_Activity.this.setResult(2, intent);
C_Activity.this.finish();
}
});
}
}
在B中 B_Activity.this.setResult(1, intent);
B_Activity.this.finish();
是关键。Android中肯定有相关方法处理这样的功能,我这种方法可能算是麻烦的了,大家如果有其他方法,欢迎留言,提出。
第二种方法是通过onNewIntent实现,这个就更加简单了。
onNewIntent:
当从栈中启动一个已经存在的Activity时,系统不会再执行onCreate方法,而是执行onNewIntent方法
(1)Activity第一启动的时候执行onCreate()---->onStart()---->onResume()等后续生命周期函数,也就时说第一次启动Activity并不会执行到onNewIntent().
(2) 而后面如果再有想启动Activity的时候,那就是执行onNewIntent()---->onResart()------>onStart()----->onResume().
(3)如果android系统由于内存不足把已存在Activity释放掉了,那么再次调用的时候会重新启动Activity即执行onCreate()---->onStart()---->onResume()等。
所以如果使用onNewIntent,执行返回的操作,1、要将此Activity的lanchMode设置为singleTask。2、另外一个Activity要通过intent请求此Activity。也可以通过Intent.FLAG_ACTIVITY_SINGLE_TOP标志启动Activity,效果跟android:launchmode="singleTask"一样。
另外,不要忘记,系统可能会随时杀掉后台运行的Activity,如果这一切发生,那么系统就会调用onCreate方法,而不调用onNewIntent方法,一个好的解决方法就是在onCreate和onNewIntent方法中调用同一个处理数据的方法。
如何区别从Activity B跳转到onNewIntent操作的Activity A呢?
是在Activity B中的intent中设置标志值,然后通过if判断:
if (intent.getBooleanExtra("LOGIN", false)) {}