在Android app开发当中,我们经常会遇到几个activity之间的跳转问题,比如A跳转到B,然后B跳转到C,然后点击C的某一项要回到A,这就存在各种数据传值的问题,今天我们就来掰扯这些activity之间的爱恨情仇。
一、方法简介
android Activity之间的跳转不只是有startActivity(Intent i)的,startActivityForResult(Intent intent, int requestCode)也是常用的方法。在一个主界面(主Activity)上能连接往许多不同子功能模块(子Activity上去),当子模块的事情做完之后就回到主界面,或许还同时返回一些子模块完成的数据交给主Activity处理。这个时候就要用到回调函数onActivityResult()。
需要注意三个方法:
- startActivityForResult(Intent intent, int requestCode)
- onActivityResult(int requestCode, int resultCode, Intent data)
- setResult(int resultCode, Intent data).
eg:
从From跳转至ToB和ToC
if(条件){
Intent intent = new Intent(this, ToB.class);
startActivityForResult(intent, REQUEST_CODE_01);//跳转至ToB
}else{
Intent intent = new Intent(this, ToC.class);
startActivityForResult(intent, REQUEST_CODE_02);//跳转至ToC
}
public void onActivityResult(int requestCode, int resultCode, Intent data){
switch (requestCode) {//请求标记
case REQUEST_CODE_01:
if(resultCode==Activity.RESULT_OK)
//do something
break;
case REQUEST_CODE_02:
//do something
break;
}
}
startActivityForResult(Intent intent, int requestCode)的参数,需要注意的是第二个,我们用的是REQUEST_CODE_01和REQUEST_CODE_02,其实这个是我们自己定义的一个int型常量,用于标记的,具体作用可在onActivityResult方法里看到,用于判断是哪个Activity传来的。
requestCode是请求标记, resultCode是返回标记。
ToB:
Intent intent = new Intent();
intent.putExtra(key, value);
setResult(Activity.RESULT_OK, intent);
finish();//结束之后会将结果传回From
这里的跳转回去,只能用setResult(int resultCode, Intent data)方法,否则会出错,无法从onActivityResult(int requestCode, int resultCode, Intent data)中的data接收到传回来的数据。
ToC:
Intent intent = new Intent();
intent.putExtra(key, value);
setResult(Activity.RESULT_OK, intent);
finish();//结束之后会将结果传回From
setResult的第一个参数对应上面onActivityResult的第二个参数。
二、三个以上的activity之间的跳转传值问题
上面介绍的我相信只要有点Android基础的人都知道,这不是我要讲的重点,我要讲的重点就是开头就说的,A跳转到B,B再跳转到C,然后C要直接回到A,甚至有可能C到D……最后一个再回到A,这种情况下,很多人就会这么干,从最后一个再启动A,可是呢,这样做就会导致A重启,原来的数据会被清空,你可能会说我先做数据保存呗,但你别忘了,有些时候数据并不是那么好保存的,而且需求可能并不是你这样子做就可以满足的。所以我接下来就用上面所说的onActivityREsult跟setResult来实现。那要怎么做呢,其实很简单,一层一层finish呗,看我下面的demo你就会明白了。
demo的大体思路就是MainActivity跳转到FirstActivity.class,然后FirstActivity.class跳转到SecondActivity.class,最后SecondActivity.class再回到MainActivity.class.
(1)MainActivity.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
public void pickTestClicked(View view) {
gotoFirstActivity();
}
private void gotoFirstActivity(){
Intent intent = new Intent(this,FirstActivity.class);
startActivityForResult(intent, Const.REQUEST_CODE_FIRST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Const.REQUEST_CODE_FIRST:
if (resultCode == Activity.RESULT_OK) {
Log.d("wu", "MainActivity.onActivityResult回调");
Toast.makeText(this, "FirstActivity数据返回", Toast.LENGTH_LONG).show();
}
break;
}
}
}
(2)FirstActivity.class
public class FirstActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity_layout);
}
public void firstActivityClick(View view){
gotoSecondActivity();
}
private void gotoSecondActivity(){
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,Const.REQUEST_CODE_SECOND);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case Const.REQUEST_CODE_SECOND:
if (resultCode == Activity.RESULT_OK ) {
Log.d("wu", "FirstActivity.onActivityResult回调");
Toast.makeText(this, "SecondActivity数据返回", Toast.LENGTH_LONG).show();
}
//这里可以把数据传回去
//比如:Intent intent = new Intent();
//intent.putExtra("data",data);
//setResult(RESULT_OK,intent);
setResult(RESULT_OK, null);
finish();
break;
}
}
}
(3)SecondActivity.class
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity_layout);
}
public void secondActivityClick(View view){
setResult(RESULT_OK, null);
finish();
}
}
三、用EventBus的方式传值
通过EventBus传值回A,这时先finish C,然后发一个信息,B收到这个信息也finish,再发一个事件,A收到这个事件后,拿到信息,这样子A的界面也就有内容填充且不会丢失内容。
//搜索版块事件传递
public class SearchResultEvent {
public boolean isStartIssueFromSearch;
public String atName;
public String atId;
public SearchResultEvent(boolean isFromSearch,String atName,String atId ){
isStartIssueFromSearch = isFromSearch;
this.atName=atName;
this.atId=atId;
}
}
C界面的某一项点击:
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Entity entity = (Entity) parent.getItemAtPosition(position);
String atName="";
String atId="";
if (entity instanceof ForumModule) {
ForumModule forumModule = (ForumModule) entity;
atName=forumModule.getName();
atId=forumModule.getId();
}
EventBus.getDefault().post(new SearchResultEvent(true,atName,atId));
EventBus.getDefault().post(new BackFinishEvent(true));
finish();
}
B界面的finish:
public void onEventMainThread(BackFinishEvent event){
if (event.isFinish){
finish();
}
}
A界面的更新信息:
public void onEventMainThread(SearchResultEvent event){
if (event.isStartIssueFromSearch){
String atName = event.atName;
String atID = event.atId;
if (mEntity == null) {
ForumModule formuModule = new ForumModule();
formuModule.setId(atID);
formuModule.setName(atName);
formuModule.setChannelName(atName);
mEntity = formuModule;
} else if (mEntity instanceof ForumModule) {
((ForumModule) mEntity).setName(atName);
((ForumModule) mEntity).setId(atID);
}
setCategoryName(mCategoryChose, mEntity);
showKeyboard();
}
这样从C点击某一项就不会导致A界面重启了。