最近項目中要實現一個相機拍攝的效果,在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不滿足條件,不會執行處理數據的代碼,也就不會崩潰了。