最近项目中要实现一个相机拍摄的效果,在A界面点击按钮,跳转到B界面(拍摄照片或录制视频),拍摄完成后跳转到C界面预览,在C界面再点击确定后,再将拍摄的照片或视频的缩略图放到A界面。
刚开始碰到时觉得有点棘手,想通过直接从C跳转到A设置Intent
的flag
属性实现,但是发现这样做会导致原先在A界面上的数据全部被清空(比如EditText
中输入的内容),在网上搜了一下找到了一种合适的解决方案。
两个Activity之间传递数据###
首先看一下,如果是两个Activity
之间传递数据该怎么做,相信大部分人应该都知道如何去写。
步骤如下:
- 在A界面调用
startActivityForResult(intent,requestCode);
- 在B界面调用
setResult(resultCode,intent); finish();
- 在A界面重写
onActivityResult(int requestCode, int resultCode, Intent data)
方法,判断requestCode
,如果符合则通过data
对象获取传递的参数。
注意在第3步中的requestCode必须与第1步的requestCode相等,否则是没有办法接收到数据的
下面给出代码:
第一步:A界面点击按钮跳转到B界面。
FirstAvtivity
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,0);//requestCode=0
}
});
第二步:B界面点击按钮返回A界面,并将TextView中显示的值传回A界面。
SecondActivity
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
String text = textview.getText().toString();
intent.putExtra("text",text);
setResult(1,intent);//requestCode=1
finish();
}
});
第三步:在A界面对返回的数据进行处理,注意此时requestCode必须为0才能接受到数据。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
...
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0){
String text = data.getStringExtra("text");
mText.setText("接受的数据为:"+text);
}
}
程序运行的效果如下:
三个Activity之间传递数据###
知道了两个Activity之间传递数据的方法,其实我们不难想到解决方案。只要进行两次两个Activity之间传递数据的过程就好了。具体步骤看下图:
- 在A界面调用
startActivityForResult(intent,requestCode);
跳转到B。 - 在B界面调用
startActivityForResult(intent,requestCode);
跳转到C(requestCode
与1不同)。 - 在C界面点击返回时调用
setResult(resultCode,intent); finish();
后退到B,并将数据传给B。 - B界面重写
onActivityResult(int requestCode, int resultCode, Intent data)
方法,判断requestCode
,如果符合则调用。setResult(resultCode,intent); finish();
继续后退一次到A,并将数据传给A。 - 在A界面重写
onActivityResult(int requestCode, int resultCode, Intent data)
方法,判断requestCode
,如果符合则通过data
对象获取传递的数据。
整个流程就是这样,下面来看看代码:
FirstActivity
public class FirstActivity extends AppCompatActivity {
private TextView mText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
Button btn = (Button) findViewById(R.id.button);
mText = (TextView) findViewById(R.id.textview);
//1、跳转到B
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,0);
}
});
}
//5、接受B的数据(实际是C的,B只是转发)并处理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0){
String text = data.getStringExtra("text");
mText.setText("接受的数据为:"+text);
}
}
}
SecondActivity
public class SecondActivity extends AppCompatActivity {
private TextView textview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Button btn = (Button) findViewById(R.id.button2);
textview = (TextView) findViewById(R.id.textView);
//2、跳转到C
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(SecondActivity.this,ThirdActivity.class);
startActivityForResult(intent,1);
}
});
}
//4、接受C的数据,返回并传递给A
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1){
Intent intent = new Intent();
String text = data.getExtras().getString("text");
intent.putExtra("text",text);
setResult(3,intent);
finish();
}
}
}
ThirdActivity
public class ThirdActivity extends AppCompatActivity {
private EditText edittext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
Button btn = (Button) findViewById(R.id.button3);
edittext= (EditText) findViewById(R.id.edittext);
//3、返回B,并传递数据,执行B的onActivityResult()方法
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("text",edittext.getText().toString());
setResult(1,intent);
finish();
}
});
}
}
最后是效果图:
可以看到跳转到C后,点击按钮直接回退到了A,并且也拿到了C传递的数据。
新的问题###
由于自己对这方面理解不准,后来发现了一个问题,这样的代码,在进行A->B->C->A这样的顺序时没有问题,而如果在B或者C界面返回时,会出现程序崩溃的情况。
问题其实很简单,比如在重写A界面onActivityResult()
方法时,只判断了requestCode
,这样,其实在B界面按下返回键同样也是能执行后面的接收数据代码的,而这时并没有从B界面传数据回来,因而获取的数据自然为空,从而导致出错。解决方法很简单:在onActivityResult()方法中同时判断requestCode与resultCode,只有同时满足两个条件,才表明接收到数据,从而执行处理数据的代码。
修改代码:
FirstActivity
//5、接受B的数据(实际是C的,B只是转发)并处理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0 && resultCode == 3){//resultCode为4中setResult(3,intent)设置的值
String text = data.getStringExtra("text");
mText.setText("接受的数据为:"+text);
}
}
SecondActivity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == 1){//添加resultCode判断
Intent intent = new Intent();
String text = data.getExtras().getString("text");
intent.putExtra("text",text);
setResult(3,intent);
finish();
}
}
这样如果从B界面直接返回的话,会因为resultCode不满足条件,不会执行处理数据的代码,也就不会崩溃了。