有时候会遇到一个很重要的ActivityA类,很多其他的ActivityB都需要向其传递参数时使用startActivityForResult()来获取结果,但是如果此ActivityB类有很多,那么ActivityA必须能够记住传进来的时候的Activity.class这个东西,不然,你无法知道Intent指向谁。
需求说明了一下,下面介绍怎么实现。我只大概看了一下Android源码没有发现有记录传进来Activity信息的类,索性按照自己的思路来做吧,挺简单的。首先做一个实验,看是否能够传递Class<?>这个类,结果证明Class<?> cls = (Class<?>) intent.getSerializableExtra("CLS");可以传递。接下来,把这些东西移到一个继承Activity的子类BaseActivity,然后工程中所有的activity类都继承此BaseActivity。
下面是几个关键类的代码:
public class TestActivity extends BaseActivity {
private static final String TAG = TestActivity.class.getSimpleName();
private Context mContext = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
mContext = this;
Intent intent1 = getIntent();
String text = intent1.getStringExtra("TEST");
Class<?> cls = getResultClass();
Log.d(TAG, "2.收到参数:" + text + " #" + cls);
if (cls != null) {
Intent intent = new Intent(mContext, cls);
Bundle bundle = new Bundle(); bundle.putString("test", "test content");
intent.putExtras(bundle); setResult(Activity.RESULT_OK, intent); finish(); Log.d(TAG, "3.回传参数");}}}
public class MainActivity extends BaseActivity {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(getApplicationContext(), TestActivity.class);
Bundle bundle = new Bundle();
bundle.putString("TEST", "TEST CONTENT");
intent.putExtras(bundle);
startActivityForResult(intent, 1, MainActivity.class);
Log.d(TAG, "1.从MainActivity开始传递参数");
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
String result = data.getStringExtra("test");
Log.d(TAG, result + " 收到了。符合预期结果"); } }
public class BaseActivity extends Activity {
protected Class<?> mStartClass = null;
protected static final String EXTRA_CLS = "CLS";
/**
* 这里仅仅是使得发送者也使用此CLS协议参数
* @param intent
* @param requestCode
* @param cls
*/
public void startActivityForResult(Intent intent, int requestCode, Class<?> cls) {
// TODO Auto-generated method stub
Bundle bundle = intent.getExtras();
if (bundle == null) {
bundle = new Bundle();
}
bundle.putSerializable(EXTRA_CLS, (Serializable)cls);
intent.putExtras(bundle);
super.startActivityForResult(intent, requestCode);
}
@Override
public Intent getIntent() {
// TODO Auto-generated method stub
Intent intent = super.getIntent();
mStartClass = (Class<?>) intent.getSerializableExtra(EXTRA_CLS);
Log.d("TAG", "mStartClass:" + mStartClass);
return intent;
}
/**
* 有可能为null
* @return
*/
protected Class<?> getResultClass() {
return mStartClass;
}
}
执行结果如下:
1.从MainActivity开始传递参数
mStartClass:class com.example.MainActivity
2.收到参数:TEST CONTENT #class com.example.MainActivity
3.回传参数
test content 收到了。符合预期结果
为什么标题说是千能方法呢?呵,因为我不敢打包票说这个方法是万能的。。。
================================ 补充 ============================================
当我在menifest中设置ActivityA为singleTask的时候发现在此类中设置setResult()后,ActivityB无法收到结果,并且ActivityB在执行startActivityForResult()后的执行顺序是onPause()->onActivityResult()->onResume()->onPause()->onCreate()这个顺序,这个顺序号奇怪哦,这么奇怪的问题肯定会有人遇到过,而且ActivityA设置setResult()后,ActivityB也无法收到此传递信息。搜了一下,貌似道理是如这篇文章所说的 http://www.cnblogs.com/lilihuang/archive/2011/08/23/2150409.html
现把此文转载至此:
singleTask, startActivityForResult不能共存的问题
原因未知,设置了目标BActivity为singleTask后,在AActivity中调用BActivity,例如
Intent intent = new Intent(this, BActivity.class);
startActivityForResult(intent, 1);
结果先会调用到 AActivity中的onActivityResult,而在BActivity设置setResult(Activity.RESULT_OL)后,AActivity的onActivityResult不会接受到通知。
解决方案:设置BActivity为singleTop.
Note that this method should only be used with Intent protocols that are defined to return a result. In other protocols (such as ACTION_MAIN
or ACTION_VIEW
), you may not get the result when you expect. 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.
http://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)