基础概念
Activity任务栈是什么?
1)栈结构,具有后进先出的特性,用于存放Activity组件;
2)退出应用程序时,必须把所有任务栈中的Activity清除出栈,任务栈才会被销毁。任务栈也可以移至后台,并且保留每一个Activity状态;
3)来自不同App的Activity也可以在一个任务栈中,每个Activity都有TaskAffinity属性,该属性指出了它希望进入的任务栈。TaskAffinity如果未指明则=包名,任务栈也有自己的Affinity属性,它的值=根Activity的TaskAffinity的值;
Activity的启动模式和使用场景?
Standard:每次启动都创建一个Activity实例;默认启动模式;
SingleTop:若Activity处于栈顶,复用栈顶实例,调用onNewIntent()。create和start不会调用;
SingleTask:检查整个栈中是否存在需要启动的Activity,存在则clearTop(),调用onNewIntent();
SingleInstance:Activity单独占有一个任务栈,具有全局唯一性。
总结:Standard和SingleTop是在同一任务栈中调度,SingleTask和SingleInstance会对任务栈进行整体调度;
使用场景:
SingleTop(推送点击跳转,登陆);SingleTask(首页);SingleInstance(呼叫来电界面)
Activity的生命周期启动顺序?
A 跳 B:A onPause >> B onCreate >> B onStart >> B onResume >> A onStop
B 返回:B onPause >> A onRestart >> A onStart >> A onResume >> B onStop >> B onDestroy
若 B 为 Dialog 或 半透明:
A 跳 B:A onPause >> B onCreate >> B onStart >> B onResume
B 返回:B onPause >> A onResume >> B onStop >> B onDestroy
竖屏锁屏与开屏:onPause >> onStop >> onRestart >> onStart >> onResume
设置为横屏锁屏:pause>>stop>>destroy>>create>>start>>resume>>pause
设置为横屏开屏:resume>>pause>>stop>>destroy>>create>>start>>resume
横竖屏切换:onPause>>onSaveInstanceState>>onStop>>onDestory>>onCreate>>
onStart>>onRestoreInstanceState>>onResume
onSaveInstanceState和onRestoreInstanceState的调用时机?
onSaveInstanceState会在以下情况被调用:SDK版本<11 pause前,<28 stop前,>28 stop后
1)HOME键; 2)选择其他程序;3)电源键;4)启动新的Activity;5)屏幕方向切换;
onSaveInstanceState保存的Bundle是存在内存中的,通过Binder将Bundle交由ActivityManager进程管理;Binder传输缓冲区是一个限制大小为1MB的区域,官方建议数据大小<=50K;
onRestoreInstanceState会在以下情况被调用:
1)屏幕方向切换;2)内存紧张导致后台程序被kill;
onRestoreInstanceState与onCreate的Bundle的区别:因为onSaveInstanceState不一定会被调用,所以onCreate的Bundle可能为空,而onRestoreInstanceState的Bundle一定不为空;
原理:
ActivityThread.perfromStopActivity中调用onSaveInstanceState,将状态保存到mActivitys中;
mActivitys.维护了一个Activity的信息表,当Activity重启时,会从Activitys中查询对应的活动记录;
ActivityClientRecord,如果有信息就会调用onRestoreInstanceState方法;
Activity的启动流程?
1)Launcher通过Binder向AMS发送startActivity请求;
2)AMS收到请求后,通过Socket通知 Zygote >> Fork >> App进程;
3)App进程向AMS发起attachApplication请求;
4)AMS收到请求后,通过Binder向App进程发送scheduleLauchActivity请求;
5)App进程收到AMS的请求后,通过Handler向ActivityThread发送LAUNCH_ACTIVITY消息;
6)ActivityThread收到消息后,反射创建目标Activity,调用其onCreate方法;
Activity之间传递数据的方式有哪些?Intent是否有大小限制?如果数据量偏大,有哪些方案?
传递方式:Intent、Bundle、静态变量、序列化对象、SharedPreferences、数据库、文件等;
Intent:传递数据用到Binder机制,Binder事务缓冲区映射内存不到1M。所以512K以下没问题,512K-1M会闪退,1M以上会报错。
大数据传输方案:非IPC>>EventBus、数据库、SharedPreferences、文件等;IPC>>共享内存
显式启动 和 隐式启动 的区别?
显式启动:startActivity(new Intent(this,Activity.class));
隐式启动:需要在清单文件添加action、data、category属性的过滤器;
隐式启动不仅可以启动自己App的Activity,还可以启动其他App的Activity。只要知道action的name就可以,如果action的name与其他相同,系统会让用户选择打开一个。没有则报错;
scheme使用场景、协议格式、如何使用?
场景:1)服务器下发跳转路径;2)H5点击锚点;3)推送消息;4)根据URL跳转指定页面;
协议格式:scheme(demo://)+ host(mineapp:) + port(9999)+ path(/detail)+ param (?)
例子:demo://mineapp:9999/detail?id=0;
使用:
1)给Activity配置过滤器,设置scheme
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="demo"
android:host="mineapp"
android:port="9999"
android:path="/detail"
/>
</intent-filter>
</activity>
2.获取参数:
Uri data = intent.getData();
String action = intent.getAction();
String scheme = intent.getScheme();
Set<String> categories = intent.getCategories();
3.判断scheme是否有效:
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("demo://mineapp:9999/detail"));
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
boolean isValid = !activities.isEmpty();
跨App启动Activity的方式,注意事项?
1)使用过滤器:如果有两个action属性值相同的Activity,系统会让用户选择启动哪个;
2)共享uid:uid标识一个应用,安装时被分配,多应用共享同一个uid时,要保证签名相同;
3)Exported:一旦设置了过滤器,exported默认为true;可通过setComponent("包名","类名");
4)权限:如果App B设置了android:permission,那么必须在App A的清单文件中uses-permission才能访问;