Android开发 Activity的详解(上)
Activity 的传值
方法一:直接把数据添加到 Intent 对象
先将数据添加到 Intent 对象,第二个界面再把数据从 Intent 中取出来。
1.MainActivity 启动 SecondActivity,传递 extra_data:
String data="Hi, SecondActivity";
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
//向intent对象添加数据
intent.putExtra("extra_data ", data );
startActivity(intent);
putExtra("A",B)
中,AB为键值对,第一个参数为键名,第二个参数为键对应的值。
2.在 SecondActivity 接收 extra_data:
//获取Intent对象
Intent intent=getIntent();
//获取传递过来的String类型的数据
String data=intent.getStringExtra("extra_data ");
getStringExtra("A")
中,参数 A 为上一个 Activity 传递的键名。
实验:
新建 App,在主界面添加一个按钮,随后设置如下点击事件:
//MainActivity部分代码
Button buttonGoTransfer = findViewById(R.id.buttonGoTransfer);
buttonGoTransfer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String data="Hi,I am EmptinessBoy!";
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtra("hello",data);
startActivity(intent);
}
});
在第二个页面获取 Intent
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
Intent intent = getIntent();
String hello = intent.getStringExtra("hello");
Toast.makeText(SecondActivity.this,hello,Toast.LENGTH_SHORT).show();
}
运行效果:
启动 Activity 并传递参数:
SecondActivity 接收到参数并使用 Toast 显示:
方法二:把数据添加到 Bundle(大篮子)对象
由于第一种方法,每次传递数据都需要存入取出,在多个 Activity 中连续传递时会显得很麻烦。如图:
因此使用 Bundle 可以很好的解决这个问题
Bundle 类用作携带数据,它类似于 Map,用于存放 key-value 名值对形式的值
1.MainActivity 向 SecondActivity 传递 bubdle 对象:
//实例化bundle对象
Bundle bundle = new Bundle();
//向bundle对象添加数据
bundle.putString("name", "张三" );
bundle.putInt("age", 20);
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
//向intent对象bundle
intent.putExtras(bundle);
startActivity(intent);
2.在 SecondActivity 接收 bubdle 对象:
//获取bundle对象
Bundle bundle = getIntent().getExtras();
//通过key为“name”来获取value即 nameString.
String name=bundle.getString("name");
int age=bundle.getInt("age");
实验:
修改上一个示例的按钮点击事件,使用 bundle 来传递多个数据:
buttonGoTransfer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putString("name","Emptinessboy");
bundle.putInt("age",19);
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
});
SecondActivity 修改接收参数的方法并使用 Toast 显示:
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String name = bundle.getString("name");
int age = bundle.getInt("age");
Toast.makeText(SecondActivity.this,"姓名:"+name+" 年龄:"+age,Toast.LENGTH_SHORT);
运行效果(bundle已经被正常传递):
Activity 接收返回值
大致流程:
- MainActivity 通过调用 startActivityForResult() 跳转到 OtherActivity。
- OtherActivity 在自己关闭之前,通过 setResult() 方法返回数据给 MainActivity。
- MainActivity 通过复写 onActivityResult() 方法来取得回传值。
首先在 MainActivity 中调用
startActivityForResult(Intent intent, int requestCode);
然后在 SecondActivity 返回
setResult(int resultCode, Intent data);
最后在 MainActivity 中调用接口来获取数值
onActivityResult(int requestCode, int resultCode, Intent data);
1、调用 startActivityForResult 方法可以开启一个获取返回值的 activity,在第一个 activity 中重写 onActivityResult 方法来接收返回的值。
2、请求码:请当同一个 activity 多次使用 startActivityForResult 方法获取返回值后,通过请求码 requestCode 来区分是哪次请求。
3、结果码:当返回多个结果时,用来区分结果。
示例代码:
MainActivity:
// 返回的结果码
public final static int REQUEST_CODE = 1;
//创建intent对象
Intent intent=new Intent(this,OtherActivity.class);
//启动OtherActivity,并发送请求码
startActivityForResult(intent,REQUEST_CODE);
SecondActivity:
EditText editText=findViewById(R.id.editText);
//数据是使用Intent返回
Intent intent = new Intent();
//把返回数据存入Intent
intent.putExtra("result", editText.getText().toString());
//设置返回数据
setResult(0,intent);
//关闭当前窗口
finish();
MainActivity 实现接口:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
……
switch (requestCode){
case REQUEST_CODE:
textView.setText(data.getStringExtra("result");break;
default:
result="未获取到数据。";
}
}
实验:
简单设计 MainActivity 的布局:
编写代码:
public class MainActivity extends AppCompatActivity {
public final static int REQUEST_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button initSecAct = findViewById(R.id.buttonInitSecAct);
initSecAct.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//发起需要结果的请求
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivityForResult(intent,REQUEST_CODE);
}
});
}
}
简单设计 SecondActivity 的布局:
编写代码:
Button buttonSubAndBack = findViewById(R.id.buttonSubAndBack);
buttonSubAndBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取输入文字
EditText editTextTextPersonName = findViewById(R.id.editTextTextPersonName);
String inputValue = editTextTextPersonName.getText().toString();
//创建Intent
Intent intent = new Intent();
intent.putExtra("inputValue",inputValue);
//返回intent
setResult(1,intent);
//返回上一级
finish();
}
});
返回 MainActivity 重写 onActivityResult():
使用 IED 进行自动生成
补全代码:
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
TextView textViewHello = findViewById(R.id.textViewHello);
switch (resultCode){
case 1:
textViewHello.setText(data.getStringExtra("inputValue"));
break;
default:
textViewHello.setText("返回码异常");
break;
}
}
最后运行效果:
一般情况下不论有没有操作 SecondActivity 里的按钮,只要从这里返回了 MainActivity,接口都会返回相同的 requestCode。
Activity 生命周期
Task 就是一个存放 Activity 栈 (A task is a stack of activities.) ,这个栈里面存放了很多 Activity ,它遵循着后进先出的原则。栈有两个动作:进栈(把对象压入到栈当中)和出栈(把栈中的第一个对象从栈里面拿出来)。
当我们将 Activity 创建好,放入栈中,先放的位于下方,后进入的位于上方。(顺序:先进后出)
四种状态
Activity在进栈与出栈的过程中,一般意义上有四种状态:
- 【运行】当 Activity 位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态;(最不会被系统回收)
- 【暂停】当 Activity 失去了焦点但仍然部分可见(如栈顶的 Activity 是透明的或者栈顶 Activity 并不是铺满整个手机屏幕),此时处于暂停状态;(系统也不会轻易回收这样的活动,除非是内存极低的情况)
- 【停止】当 Activity 被其他 Activity 完全遮挡,此时此 Activity 对用户不可见,此时处于停止状态;(内存中保留Activity对象,当内存较低时系统会回收这样的活动)
- 【非活动】当 Activity 由于人为或系统原因(如低内存等)被销毁,此时处于销毁状态。
七个回调方法
在每个不同的状态阶段,Adnroid 系统对 Activity 内相应的方法进行了回调。因此,我们在程序中写 Activity 时,一般都是继承 Activity 类并重写相应的回调方法。
- onCreate() 当Activity第一次被创建时调用,完成活动的初始化操作。
- onStart() 当用户可以看到这个Activity时调用。
- onResume() 当获得了用户的焦点时,就是用户点击了屏幕。
- onPause() 当系统准备启动或回复另一个活动时调用。
- onStop() 当活动完全不可见时调用,当新启动的活动是对话框式的,还处于可见时,该方法不会被调用。
- onDestroy() 活动被销毁时调用。
- onRestart() 当活动由停止状态变为运行状态时调用。
示意图
三种生命周期
1.完整生命周期: 活动在 onCreate() 方法和 onDestroy() 方法之间所经历的,就是完整生命周期。一般情况下,一个活动会在onCreate()方法中完成各种初始化, onDestroy()方法中完成释放资源的操作。
2.前台生命周期: 活动在 onResume() 方法和 onPause() 方法之间所经历的就是前台生命周期。在前台生命周期内,活动总是处于运行状态,此时的活动可以与用户进行交互。
3.可视生命周期: 活动在 onStart() 方法与 onStop() 方法之间所经历的,就是可视生命周期。在可视生命周期内,活动对于用户是可见的,但可能无法和用户进行交互。
实验
重写生命周期的方法,并打印输出日志
完整生命周期实验:
启动 Activity 后 onCreate() –> onStart() –> onResume()
按 Back 键 –> onPause() –> onStop() –> onDestroy()
这里重写了 HelloWorld程序 完整生命周期的所有方法
运行后,程序启动时打印了前三条日志,按下返回键后打印了后三条日志:
前台生命周期实验:
新建一个 TestActivity,并在 MainActivity 中设置按钮点击跳转。
在 AndroidManifest.xml 中,将第二个 Activity 的样式设为 dialog 对话框,来实现半遮挡效果:
<activity
android:name=".TestActivity"
android:theme="@style/Theme.AppCompat.Dialog"
android:label="TestActivity"/>
运行程序测试:
可以看到,当点击按钮后,MainActivity 被遮挡时,输出 onPause 的日志,按下返回键返回 MainActivity 时,输出 onResume 日志。
可视生命周期实验:
不改变示例程序,我们在程序运行时呼入电话:
可以看到:
2020-04-19 01:47:25.803 30014-30014/com.emptinessboy.testlifecycle D/MainActivity: onPause: 被暂停
2020-04-19 01:47:27.089 30014-30014/com.emptinessboy.testlifecycle D/MainActivity: onStop: 被停止
挂掉电话后则输出了(图略):
2020-04-19 01:47:48.733 30014-30014/com.emptinessboy.testlifecycle D/MainActivity: onStart: 正在运行
2020-04-19 01:47:48.734 30014-30014/com.emptinessboy.testlifecycle D/MainActivity: onResume: 被重新开始

This blog is under a CC BY-NC-ND 4.0 Unported License
本文链接:https://coding.emptinessboy.com/2020/04/Android%E5%BC%80%E5%8F%91-Activity%E7%9A%84%E8%AF%A6%E8%A7%A3%EF%BC%88%E4%B8%8A%EF%BC%89/