1.Activity的启动流程
Launcher进程请求AMS
AMS发送创建应用进程请求
Zygote进程接受请求并孵化应用进程
应用进程启动ActivityThread
应用进程绑定到AMS
AMS发送启动Activity的请求
ActivityThread的Handler处理启动Activity的请求
2.onSaveInstanceState,onRestoreInstanceState的调用时机
系统的回收机制会未在用户主动操作的情况下销毁Activity,而为了避免系统回收Activity导致数据丢失,
Android为我们提供了onSaveInstanceState和onRestoreInstanceState用于保存和恢复数据。
系统只在Activity异常终止的时候才会调用onSaveInstanceState和onRestoreInstanceState来储存和恢复数据,正常销毁Activity不会触发这个过程。
onSaveInstanceState:
1.从最近的应用中选择运行其他程序时
2…当用户按下home键时
3.屏幕方向切换时
4.按下电源按键(关闭屏幕显示)时
5.从当前activity启动一个新的activity时:onPause—>onSaveInstanceState—>onStop
onRestoreInstanceState只有在Activity确实被系统回收,重新创建Activity的情况下才会被调用:
比如屏幕方向切换时,activity的生命周期如下
onPause–》onSaveInstanceState–》onStop–》onDestroy–》onCreate–》onStart–》onRestoreInstanceState–》onResume
在这里onRestoreInstanceState被调用,因为Activity确实被系统回收了又重新创建了新的Activity
但是按home键返回桌面又马上点击应用图标回到原来页面时,activity生命周期如下:
onPause–》onSaveInstanceState–》onStop–》onRestart–》onStart–》onResume
因为activity没有被系统回收,因此onRestoreInstanceState没有被调用
3.activity的启动模式和使用场景
standard:默认模式
singletop:如果要启动的activity已经在栈顶,不会重新创建activity,只会调用该activity的onNewIntent方法;如果要启动的activity不在栈顶,则重新创建该activity实例
singleTask:如果要启动的activity已经存在于栈中,则不会创建该activity实例,将栈中位于该activity上的所有的activity出栈,同时该activity的onNewIntent方法会被调用
singleInstance:创建一个新栈,将要启动的activity压入新栈中,新栈中只会存在这一个activity实例
4.activityA跳转activityB,再按返回键,生命周期执行顺序
A跳转B会执行:A onPause–》B onCreate–》B onStart–》B onResume–》A onStop
在B按下返回键会执行:B onPause–》A onRestart—》A onStart–》A onResume–》B onStop–》B onDestory
当B的launchMode为singleInstance,singleTask且对应的B activity有可复用的实例时,生命周期回调如下:
A.onPause -> B.onNewIntent -> B.onRestart -> B.onStart -> B.onResume -> A.onStop ->
(如果A被移出栈的话还有一个A.onDestory)
当B Activity的launchMode为singletop且B Activity已经在栈顶时(一些特殊情况如通知栏点击、连点),此时只有B页面自己有生命周期变化B.onPause -> B.onNewIntent -> B.onResume
5.横竖屏切换,按home键,按返回键,锁屏与解锁屏幕,跳转透明Activity界面,启动一个Theme为Dialog的Activity,弹出Dialog时Activity的生命周期
横竖屏切换:
1.不配置Activity的androidconfigChanges,或设置Activity的androidconfigChanges=“orientation”,或设置Activity的android:configChanges=“orientation|keyboardHidden”,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行一次。
2.配置ndroid:configChanges=“orientation|keyboardHidden|screenSize”,才不会销毁activity,且只调用onConfigurationChanged方法。
按home键:
onPause–》onStop–》onRestart–》onStart–》onResume
按返回键:
onPause–》onStop–》onDestory–》onCreate–》onStart–》onResume
锁屏与解锁屏幕:
锁屏只会调用onPause不会调用onStop,解锁屏幕会调用onResume
弹出Dialog:
直接通过WindowManager.addView显示的(没有经过AMS),所以不会对生命周期有任何影响
跳转透明Activity界面,启动一个Theme为Dialog的Activity:
onPause–》onCreate–》onStart–》onResume(Activity不会回调onStop,因为只有Activity切到后台不可见才会回调onStop)
6.onStart和onResume、onPause和onStop的区别
onStart和onResume从Activity可见可交互区分:
onStart用户可以看到部分activity但不能与它交互;onResume可以获得activity的焦点,能够与用户交互
onPause和onStop从Activity是否位于前台,是否有焦点区分
onPause表示当前页面失去焦点;onStop表示当前页面不可见
例如:在activity里面打开一个diaolog的主体页面,该activity会执行onPause但不会执行onStop
7.Activity之间传递数据的方式Intent是否有大小限制,如果传递的数据量偏大,有哪些方案
传512k以下的数据可以正常传递,
传512k~1024K的数据会出错、闪退,
传1024k以上的数据会报错:TranscationTooLargeException
考虑到Intent还包括要启动的Activity等信息,实际可以传的数据略小于512k
数据偏大时的方案:
将数据保存到全局Application中
使用单例数据类
持久化数据
8.Activity的onNewIntent方法什么时候执行
当ActivityA的LaunchMode为Singletop时,如果ActivityA在栈顶,且现在要再启动ActivityA,这时会调用onNewIntent()方法;
当ActivityA的LaunchMode为SingleInstance,SingleTask时,如果已经ActivityA已经在堆栈中,那么此时再次启动会调用onNewIntent()方法;
9.显式启动和隐式启动
显式启动需要明确地指定被启动对象的组件信息,包括类名和包名
隐式启动是通过在AndroidManifest文件中设置action、data、category,让系统来筛选出合适的Activity
action匹配规则:
intent-filter action可以设置多条
intent中的action只要与intent-filter其中一条匹配成功即可,且intent中的action最多只有一条
intent-filter内必须至少包含一个action
category匹配规则:
intent-filter内必须至少包含一个category,android:name为android.intent.category.DEFAULT
intent-filter category可以设置多条
intent中,category也可以有多条
intent中所有的category都可以在intent-filter中找到一样的才算匹配成功
data匹配规则:
intent-fiter中可以设置多个data
intent中只能设置一个data
intent-fiter中指定了data,intent中就要指定其中一个data
10.scheme使用场景,协议格式,如何使用
scheme是一种页面内跳转协议,是一种非常好的实现机制,通过自己定义的scheme协议可以非常方便的跳转app中的各个页面
测试:
AndroidManifest.xml
<activity android:name="com.example.testapplication.main.mine.AboutUsActivity"
android:exported="true">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="https"/>
</intent-filter>
</activity>
mineFragment
//关于我们
Rl_about_us.setonClickListener {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("https://www.baidu.com")
startActivity(intent)
}
效果如下:
将AndroidManifest.xml中修改为
点击效果直接使用浏览器打开网页,不会弹出询问弹窗
11.onCreate和onRestoreInstance方法中恢复数据时的区别
onRestoreInstance不一定会被调用,因为只有被回收再次复用的activity才会回调该方法
onCreate里的Bundle参数可能为空,一定要做非空判断。而onRestoreInstance的Bundle参数一定不会是空值。
12.activity间传递数据的方式
通过Intent传递(Intent.putExtra的内部也是维护一个Bundle,因此,通过putExtra放入的数据取出时也可以通过Bundle去取)
通过全局变量传递
通过SharedPreferences传递
通过数据库传递
通过文件传递
13.跨App启动Activity注意事项
三种跨App启动的方式:
1、通过自定义action启动
WayealmoduleApp.mineFragment
//关于我们
Rl_aboutUs.setonClickListener {
val intent = Intent()
intent.action = "transBundle.app"
startActivity(intent)
// startActivity(Intent(context, AboutUsActivity::class.java))
}
TestApplicationApp.AndroidManifest.xml
<activity android:name="com.example.testapplication.main.mine.AboutUsActivity"
android:exported="true">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="transBundle.app"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
2.通过在Intent中通过指定包名和类名来查找
WayealmoduleApp.mineFragment
val componetName = ComponentName(
"com.example.testapplication",
"com.example.testapplication.main.mine.AboutUsActivity"
)
try {
val intent = Intent()
intent.component = componetName
startActivity(intent)
}catch (e :Exception){
throw e
}
3、通过scheme启动
WayealmoduleApp.mineFragment
Rl_aboutUs.setonClickListener {
val uri = Uri.parse("app://my.test")
val intent = Intent("transBundle.app", uri)
startActivity(intent)
// startActivity(Intent(context, AboutUsActivity::class.java))
}
TestApplicationApp.AndroidManifest.xml
<activity
android:name="com.example.testapplication.main.mine.modifypwd.ModifyPasswordActivity"
android:exported="true"
android:process=".remote">
<intent-filter>
<action android:name="transBundle.app"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="app" android:host="my.test"/>
</intent-filter>
</activity>
注意: 上述所有被调用的Activity的android:exported="true"一定要设置为true,表示当前Activity可以被另一个Application的组件调用。
14.使用scheme在H5里面调用Activity
h5:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<a href="taobao://app/path?query1=1&query2=true">打开APP</a>
</body>
<html>
TestApplicationApp.AndroidManifest.xml
<activity android:name="com.example.testapplication.main.mine.AboutUsActivity"
android:exported="true">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.broWSABLE"/>
<category android:name="android.intent.category.APP_broWSER"/>
<data
android:scheme="taobao"
android:host="app"
android:path="/path"/>
</intent-filter>
</activity>
15.解释一下什么是uid什么是pid
uid: android中uid用于标识一个应用程序,uid在应用安装时被分配,并且在应用存在于手机上期间,都不会改变。一个应用程序只能有一个uid,多个应用可以使用sharedUserId 方式共享同一个uid,前提是这些应用的签名要相同。
pid : 进程ID,可变的
16.Activity任务栈是什么
1.Activity任务栈又称为Task,是一个栈结构,具有先进先出的特性,用于存放我们的Activity组件
2.一个任务栈包含一个Activity的集合,只有在栈顶的Activity才可以和用户进行交互
3.退出应用程序时,必须把所有任务栈中所有的Activity清除出栈时,任务栈才会被销毁。当然任务栈可以移动到后台,并且保留每一个Activity的状态。
4.对应AMS中的ActivityRecord、TaskRecord、ActivityStack
17.Activity有哪些常用的标记位(FLAG)
FLAG_ACTIVITY_NEW_TASK
此标记位作用是为Activity指定“singleTask”启动模式,其效果和在XML中指定相同android:launchMode=“singleTask”
FLAG_ACTIVITY_SINGLE_TOP
此标记位作用是为Activity指定“singletop”启动模式,其效果和在XML中指定相同android:launchMode=“singletop”
FLAG_ACTIVITY_CLEAR_TOP
具有此标记位的Activity,当它启动时,在同一个任务栈中位于它上面的Activity都要出栈。此标记位一般会和singleTask启动模式一起出现,此情况下,若被启动的Activity实例存在,则系统会调用它的onNewIntent。
原文地址:https://www.jb51.cc/wenti/3283226.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。