【代码是最好得老师】
1.概要
Activity 是四大组件之首
2.Activity生命周期
- 典型情况下的生命周期:
是指在有用户参与的情况下,Activity所经过的生命周期的改变;
- 异常情况下的生命周期:
是指Activity 被系统回收 或者由于当前设备的 Configuration发生改变 从而导致Activity被销毁重建
2.1典型生命周期
- 当用户按back键回退时,回调如下:onPause -> onStop -> onDestroy
2.2异常生命周期
- 如果突然旋转屏幕,由于系统配置发生了改变,在默认情况下,Activity就会被销毁并且重新创建
- Activity是在异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity的状态
- Activity被意外终止时,Activity会调用onSaveInstanceState去保存数据,然后Activity会委托Window去保存数据,接着Window再委托它上面的顶级容器去保存数据。顶层容器是一个ViewGroup,一般来说它很可能是DecorView。最后顶层容器再去一一通知它的子元素来保存数据,这样整个数据保存过程就完成了
- onRestoreInstanceState一旦被调用,其参数Bundle savedInstanceState一定是有值的,我们不用额外地判断是否为空;但是onCreate不行,onCreate如果是正常启动的话,其参数Bundle savedInstanceState为null,所以必须要额外判断
2.3 configChanges
不想让Activity在屏幕旋转的时候重新创建,就可以给configChanges属性添加orientation这个值
android:configChanges="orientation"
android:configChanges="orientation|screenSize"
android:configChanges="orientation|keyboardHidden"
Activity的确没有重新创建,并且也没有调用onSaveInstanceState和onRestoreInstanceState来存储和恢复数据,取而代之的是系统调用了Activity的onConfigurationChanged方法
上面表格中的项目很多,但是我们常用的只有locale、orientation和keyboardHidden这三个选项
3.Activity的启动过程
- 启动Activity的请求会交由Instrumentation处理
- Instrumentation通过Binder向AMS发送请求
- AMS(Activity Manager Service)内部维护着一个ActivityStack,并负责同步栈内Activity的状态
- AMS通过ActivityThread去同步Activity状态,完成生命周期方法调用
4.Activity 启动模式
- addFlags的优先级要高于xml方式
- clearTaskOnLaunch设置该属性后,每次返回该Activity时,都将该Activity之上的所有Activity清除
- TaskAffinity:标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名
- singleTop & singleInstance 这两种启动模式,,使用startActivityForResult()方法启动另一个Activity ,那么系统更直接返回 Activity.RESULT_CANCELED,不会等待返回,因为android在Framework层做了对这两启动模式的限制
根本: 不同Task栈,不能进行数据数据,如果一定要,只能通过Intent来绑定数据
4.1标准模式-standard
- 系统默认的启动模式
- 每次启动创建一个新的实例activity
- 谁启动了该activity实例,该activity就在其栈中
- 当我们用ApplicationContext去启动standard模式的Activity的时候会报错
原因:standard模式的Activity默认会进入启动它的Activity所属的任务栈;applicationContext没有任务栈;
解决: 启动Activity指定**intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)**标记位,singleTask模式
4.2栈顶复用模式-singleTop
- 如果目标activity实例位于栈顶,activity不会重新创建,同时onNewIntent()方法会被调用,不会调用onCreate()、onStart()
- 如果栈顶无目标实例,则重新创建activity
4.3栈内复用模式-singleTask【AndroidManifest的clearTop】
- 可以理解为栈内单例模式的activity,只要栈内存在,就不会重新创建,且onNewIntent()方法会被调用,不会调用onCreate()、onStart()
- 启动时,会先查找activity的目标栈,不存在则创建栈,然后创建实例
- 如果目标栈存在,查找栈内是否存在目标activity,不存在则创建。
- 如果目标栈存在目标activity,且不在栈顶,则会将activity之上的实例出栈,将activity置栈顶
4.4单实例模式-singleInstance
- 加强版的singleTask模式,即activity独立运行在单独栈中
4.5 Intent的Flags
- FLAG_ACTIVITY_NEW_TASK:为activity指定【singleTask】启动模式
- FLAG_ACTIVITY_SINGLE_TOP:指定【singleTop】
- FLAG_ACTIVITY_CLEAR_TOP:与FLAG_ACTIVITY_NEW_TASK配合使用,效果同【singleTask】
- FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:Activity不会出现在历史Activity的列表中,一次性activity
5.Activity数据传递
5.1携带数据
step1:Activity1发送数据
String data = "hello world";
Intent intent = new Intent(MainActivity.this,FirstActivity.class);
intent.putExtra("mydata",data);
startActivity(intent);
step2:Activity2接受数据
Intent intent = getIntent();
String data = intent.getStringExtra("mydata");
Toast.makeText(this, "传递过来的值是" + data, Toast.LENGTH_SHORT).show();
5.2返回数据
step1:activity1启动方式:要求返回数据
Intent intent = new Intent(MainActivity.this, FirstActivity.class);
startActivityForResult(intent, 1);
step2:activity2设置返回数据
Intent intent = new Intent();
intent.putExtra("data_return","hello");
setResult(RESULT_OK,intent);
finish();
step3:activity1接收返回的数据
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
String returnedData = data.getStringExtra("data_return");
Log.e("MainActivity",returnedData);
}
}
}
6.activity全局管理
仅提供思路,实际开发按需更换为软引用方式
step1:Activity管理类
public class ActivityCollector{
public static List<Activity> activities = new ArrayList<>();
public static void addActivity( Activity activity ){
activities.add( activity );
}
public static void removeActivity( Activity activity ){
activities.remove( activity );
}
public static void finishAll(){
for( Activity activity : activities){
activity.finish();
}
}
}
step2:BaseActivity
public class BaseActivity extends AppCompatActivity{
@Override
protected void onCreate( Bundle savedInstanceState ){
super.onCreate( savedInstanceState );
Log.d( "BaseActivity" , getClass().getSimpleName() );
ActivityCollector.addActivity(this);
}
@Override
public void onDestory(){
super.onDestory();
ActivityCollector.removeActivity(this);
}
}
step3:XxxActivity
public class XxxActivity extends BaseActivity{
//....
private void exitApp(){
ActivityCollector.finishAll();
//or force exit
//android.os.Process.killProcess(android.os.Process.myPid());
}
//...
}