Activity是Android四大组件之一,在Android系统中是以界面的形式进行体现
一、生命周期
生命周期方法解读
- onCreate():Activity开始创建时调用(生命周期的第一个方法),做一些初始化的工作,比如setContentView()方法
- onStart():Activity开始启动时调用(此时Activity还不可见,无法与用户进行交互)
- onResume():当Activity第一次启动完成或者当前Activity被遮挡住一部分(进入了onPause())重新回到前台时调用,比如弹窗消失。当onResume()方法执行完毕之后Activity就进入了运行状态。
- onPause():Activity停止但是当前Activity还是处于用户可见状态,比如出现弹窗;在onPause()方法中不能进行耗时操作(当前Activity通过Intent启动另一个Activity时,会先执行当前Activity的onPause()方法,再去执行另一个Activity的生命周期)
- onStop():Activity完全被挡住不可见时调用(在onStop()中做一些回收资源的操作)
- onDestroy():Activity被销毁时
- onRestart():处于stop()状态也就是完全不可见的Activity重新回到前台时调用(重新回到前台不会调用onCreate()方法,因为此时Activity还未销毁)
- Activity启动时:onCreate()--->onStart()--->onResume()--->运行状态
- Activity被完全覆盖或者点击home键:onPause()--->onStop()--->onDestroy(),如果在Activity还未销毁之前重新回到了前台:onPause()--->onStop()--->onRestart()--->onStart()--->onResume()
其他注意事项
- onStart()和onStop()从Activity是否完全可见的角度进行回调
- onPause()和onResume()从Activity是否位于前台(UI最顶层)的角度进行回调
二、启动模式
任务栈
介绍启动模式之前要先介绍一下任务栈:
affinity属性:
affinity是Activity的一个属性,在Manifest中对应taskAffinity属性,拥有相同affinity属性的Activity属于同一个任务栈,任务栈也具有affinity这个属性,任务栈的这个属性由根Activity决定;
默认情况下,所有的Activity的affinity属性继承自Application,所以Application也具有这个属性,Application的默认affinity为包名。
应用程序在启动时就创建了一个任务栈(先近后出),用于存储当前应用的Activity实例,在默认情况下,所有的Activity都属于同一个任务栈;一个任务栈包含了一个Activity的集合,然后有序的选择一个Activity和用户进行交互,只有在栈顶的Activity才可以和用户进行交互;只有当任务栈中所有的Activity全部清除出栈时任务栈才会销毁,程序退出。
启动模式
在Manifest对应的Activity中通过android:launchMode属性进行设置
- standard:默认的启动模式。不需要在Manifest对应的Activity中设置android:launchMode属性。
每次启动Activity都会生成一个新的Activity实例置于任务栈栈顶,不管有没有已存在的实例都会进行创建。 - singleTop:栈顶复用模式。Activity设置这个启动模式之后,在启动Activity时,会先判断当前任务栈的栈顶是否存在当前要启动的Activity的实例,如果存在则不创建实例,如果不存在就创建实例置于栈顶。
场景:假如说一个app在通知栏推送了好几条消息,点击一条推送消息就会进入一个Activity,如果设置为默认模式的话,就会启动多个Activity,但是设置为singleTop模式的话只需要传入不同的数据就可以显示不同的页面。 - singleTask:和singleTop这个启动模式类似,但是singleTop针对的是任务栈的栈顶,singleTask针对的是整个任务栈。启动一个新的Activity时,会判断任务栈中是否存在Activity实例,如果不存在的话就创建一个新的实例,如果存在就会将任务栈中此Activity之上的所有Activity清除出栈,是一种更为霸道的方式。
场景:一般用于系统主界面(因为在主界面点击Back之后应该是退出APP)
-singleInstance:单例模式。启动Activity时会为这个Activity分配一个新的affinity属性,并且创建一个新的任务栈,并且这个栈中只能存在这一个Activity,如果之前已经创建过则不会创建新的实例。
场景:系统Launcher,来电界面
三、Activity状态保存和恢复
哪些状态需要保存状态
最简单的就是数据了。假如我们当前正在操作一些数据,但是数据还没有处理完成,碰到一些突发情况,这时就需要保存数据。
什么情况下需要保存状态
按照官方的说法就是在处理运行时配置变更的时候。
总结也就是如下几种情况:
- 点击back键
- 锁屏
- 点击home键
- 有其他App进入前台(比如来电)
- 启动了新的Activity
- 屏幕方向发生旋转
- APP被系统kill掉
状态为什么会丢失
创建一个Activity,重写其生命周期的方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy: ");
}
/**
* 2022-02-19 18:27:21.839 19513-19513/com.example.myapplication E/MainActivity: onCreate:
* 2022-02-19 18:28:17.984 19513-19513/com.example.myapplication E/MainActivity: onDestroy:
* 2022-02-19 18:28:18.049 19513-19513/com.example.myapplication E/MainActivity: onCreate:
*/
旋转一下屏幕,可以发现Activity被重新创建了
如何保存和恢复状态
在Activity中在重写另外两个方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG, "onCreate: ");
}
@Override
protected void onStart() {
super.onStart();
Log.e(TAG, "onStart: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy: ");
}
@Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume: ");
}
@Override
protected void onStop() {
super.onStop();
Log.e(TAG, "onStop: ");
}
@Override
protected void onPause() {
Log.e(TAG, "onPause: ");
super.onPause();
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e(TAG, "onRestoreInstanceState: ");
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
Log.e(TAG, "onSaveInstanceState: ");
}
/**
* 2022-02-19 19:07:16.052 20460-20460/com.example.myapplication E/MainActivity: onCreate:
* 2022-02-19 19:07:16.056 20460-20460/com.example.myapplication E/MainActivity: onStart:
* 2022-02-19 19:07:16.060 20460-20460/com.example.myapplication E/MainActivity: onResume:
* 2022-02-19 19:07:44.421 20460-20460/com.example.myapplication E/MainActivity: onPause:
* 2022-02-19 19:07:44.431 20460-20460/com.example.myapplication E/MainActivity: onStop:
* 2022-02-19 19:07:44.433 20460-20460/com.example.myapplication E/MainActivity: onSaveInstanceState:
* 2022-02-19 19:07:44.434 20460-20460/com.example.myapplication E/MainActivity: onDestroy:
* 2022-02-19 19:07:44.490 20460-20460/com.example.myapplication E/MainActivity: onCreate:
* 2022-02-19 19:07:44.497 20460-20460/com.example.myapplication E/MainActivity: onStart:
* 2022-02-19 19:07:44.498 20460-20460/com.example.myapplication E/MainActivity: onRestoreInstanceState:
* 2022-02-19 19:07:44.500 20460-20460/com.example.myapplication E/MainActivity: onResume:
*/
在Activity创建成功之后,旋转屏幕,可以发现在Activity销毁时会在onDestroy()之前调用onSaveInstanceState方法,然后在销毁Activity,在onResume()之前调用onRestoreInstanceState方法。
onSaveInstanceState方法就是用来保存Activity中的数据的,而onRestoreInstanceState可以获取在onSaveInstanceState保存的数据。
然后发现这两个方法的参数都是Bundle类型的,所以说我们可以通过Bundle来保存和恢复数据
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
savedInstanceState.putString("data","bundle");
Log.e(TAG, "onRestoreInstanceState: ");
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
String data = outState.getString("data");
Log.e(TAG, "onSaveInstanceState: ");
}
四、Activity之间的通信方式
方式一:通过Intent传值
Intent intent=new Intent(A.this,B.class);
intent.putExtra("data",100);
startActivity(intent);
//Activity B中
Intent intent=getIntent();
intent.getIntExtra("data",0);
方式二:通过Bundle
//Activity A启动ActivityB
Intent intent=new Intent(A.this,B.class);
Bundle bundle=new Bundle();
bundle.putString("data","data");
intent.putExtra(bundle);
startActivity(intent);
//Activity B中
Bundle bundle=getIntent().getExtras();
String data=bundle.getString("data");
方式三:通过全局变量(Application)
- 创建一个Application的子类,并且声明一个全局变量,同时在Manfest中引入当前Application
//应用的全局变量
public Map<String,Object> data = new HashMap<String, Object>();
- 在Activity A合适的位置存储数据到HashMap中,在Activity B中通过map.get()取出数据
方式四:回传数据
假设一个场景,QQ或者微信我们在从相册选取一张图片作为头像时应该怎么传递数据
Activity A:通过startActivityForResult(intent requestcode);方法
Activity B:setResult(resultCode,intent);
Activity A:重写onActivityResult();
public class MainActivity extends Activity {
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
}
public void show(View v)
{
Intent intent = new Intent(MainActivity.this, InfoActivity.class);
//带返回数据启动Activity
startActivityForResult(intent, 110);
}
/**
* 获取回传的数据
*
* int requestCode 请求码
* int resultCode 结果码
* Intent data 意图(带着返回参数)
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==110 && resultCode == RESULT_OK)
{
//为图片控件设置内容
int imageId = data.getIntExtra("imageId", R.drawable.ic_launcher);
iv.setImageResource(imageId);
}
}
}
public class InfoActivity extends Activity {
private RadioGroup rg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_info);
rg = (RadioGroup) findViewById(R.id.rg);
}
//点击按钮后,将图片的ID 回传给MainActivity页面
public void submit(View v)
{
//1, 得到当前选中的RadionButton的id
int checkId = rg.getCheckedRadioButtonId();
//图片的ID
int imageId = R.drawable.ic_launcher;
switch (checkId) :
case R.id.rb1:
imageId = R.drawable.img_31;
break;
case R.id.rb2:
imageId = R.drawable.img_32;
break;
}
/**
* 通过startActivityForResult() 开启的界面, 需要有返回值,
*
* 则必须要通过 setResult() 方法返回数据
*
* resultCode 返回码
*
* data intent意图对象
*/
Intent data = new Intent();
data.putExtra("imageId", imageId);
setResult(RESULT_OK, data);
//关闭当前Activity页面
finish();
}
}