Activity启动和数据传递
概述
项目过程中,Activity通常会需要启动另外一个Activity,启动另外一个Activity的方法有两种:startActivity()和startActivityForResult()。
这两种方法都需要一个Intent对象。
startActivity
如果新启动的 Activity 不需要返回结果,当前 Activity 可以通过调用 startActivity() 方法来启动它。
Intent intent = new Intent(context,LoginActivity.class);
startActivity(intent);
Activity之间需要传递数据时,可以使用Intent对象进行此类操作,而这就是Intent的真正价值所在。
Intent intent = new Intent(context,LoginActivity.class);
intent.putExtra("key","LoginActivity");
startActivity(intent);
public class LoginActivity extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Intent intent = getIntent();
String value = intent.getStringExtra("key");
Log.d(LOG_TAG,"value is " + value);
}
}
输出log:
2020-08-18 16:46:25.415 16797-16797/com.example.myactivity D/MyActivity: value is LoginActivity
startActivityForResult
如果需要再Activity结束时从Activity中获取返回结果,例如启动一个新Activity后,需要用户执行一系列的操作,当用户关闭当前Activity时,需要获取用户的一些操作产生的数据时,可以使用该方法。
当新启动Activity 退出时,它可以调用 setResult(int) 将数据返回到其上级。新启动Activity必须始终提供结果代码,该结果代码可以是标准结果 RESULT_CANCELED、RESULT_OK,也可以是从 RESULT_FIRST_USER 开始的任何自定义值。此外,新启动Activity 可以根据需要返回包含它所需的任何其他数据的 Intent 对象。上级Activity 使用 onActivityResult(int, int, Intent) 方法,以及上级 Activity最初提供的整数标识符来接收信息。
private void initView(){
btnStart = (Button) findViewById(R.id.btn_start);
tvStart = (TextView) findViewById(R.id.tv_start);
btnStart.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(context,LoginActivity.class);
startActivityForResult(intent,TEXT_INT_CODE);
}
}
);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == TEXT_INT_CODE){
if(resultCode == RESULT_OK){
String result = data.getStringExtra("result");
tvStart.setText(result);
}else if(resultCode == RESULT_CANCELED){
Log.d(LOG_TAG,"新启动activity发生意外情况时,如崩溃,则返回的resultCode是RESULT_CANCELED");
}else if(resultCode == RESULT_FIRST_USER){
}
}
}
public class LoginActivity extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Button btnBack = (Button) findViewById(R.id.btn_back);
btnBack.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.putExtra("result", "back from loginActivity");
setResult(TEXT_INT_CODE, intent);
finish();//要调用finish()销毁当前的Activity,否则无法返回到原来的Activity,就无法执行原来Activity的onActivityResult函数
}
}
);
}
}
注意
1.点击手机返回键或者轻触home键返回时,会发生闪退问题,这是因为返回时没有数据,报错Log如下:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Intent.getStringExtra(java.lang.String)' on a null object reference
at com.example.myactivity.MainActivity.onActivityResult(MainActivity.java:78)
at android.app.Activity.dispatchActivityResult(Activity.java:8413)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5464)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5512)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
假如需要在点击返回键或者轻触home时实现相同效果,那么需要捕获Back键事件,处理代码如下:
public class LoginActivity extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Button btnBack = (Button) findViewById(R.id.btn_back);
btnBack.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
testBack();
}
}
);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
testBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void testBack(){
Intent intent = new Intent();
intent.putExtra("result", "back from loginActivity");
setResult(TEXT_INT_CODE, intent);
finish();
}
}
2.当在第一个Activity界面快速点击启动按钮时,会发现有可能创建启动多个Activity,这是我们在项目中不想看到的现象。解决这个问题的一个方法就是在AndroidManifest.xml文件中配置activity的地方加上android:launchMode=“singleTop”。
<activity android:name=".LoginActivity"
android:launchMode="singleTop">
</activity>
两个Activity之间的启动流程
当一个 Activity 启动另一个 Activity 时,它们都会经历生命周期转换。第一个 Activity 停止运行并进入“已暂停”或“已停止”状态,同时创建另一个 Activity。如果这些 Activity 共享一些数据时,需要明确的是,第一个Activity在创建第二个 Activity 之前并未完全停止。而是第二个Activity启动的过程与第一个 Activity停止的过程重叠。
以下是 Activity A 启动 Activity B 时的操作发生顺序:
- Activity A 的 onPause() 方法执行。
- Activity B 的 onCreate()、onStart() 和 onResume() 方法依次执行(Activity B 现在具有用户焦点)。
- 然后,如果 Activity A 在屏幕上不再显示,其 onStop() 方法执行。