1. Activity的启动模式有哪些?
属性 | 描述 | 作用 |
---|---|---|
standard | 每启动一个新的Activity就加入到任务栈中,并处于栈顶。 | 默认启动模式 |
singleTop | 如果该Activity在任务栈的栈顶,那么就不会创建新的Activity,而是复用该Activity,并走onNewIntent的回调。如果不在栈顶,则创建新的实例 | 1. 通知栏跳转当前Activity 2. Activity自己跳转自己 |
singleTask | 如果当前的任务栈中有该Activity,则会把该实例上面的Activity退栈,并走onNewIntent的回调。如果不在当前栈,则创建新的实例 | 作为应用首页跳转 |
singleInstance | 创建新的任务栈管理该活动,且栈中只会存在该Activity实例 ,如果该实例存在则直接复用,并走onNewIntent的回调,否则创建 | 作为独立的页面给其他应用调用或者跳转,不会影响自己的任务栈和其他应用的任务栈 |
P.S. 对于singleInstance
来说,如果是调用startActivityForResult,会在当前栈打开新的Activity,如果是startActivity会在其他栈打开
2. Flag的作用
- FLAG_ACTIVITY_NEW_TASK: 1.如果taskAffinity一致,则会在当前栈打开,如果不一致,就会在新的任务栈打开。2.用于Context或者BaseApplication来startActivity
- FLAG_ACTIVITY_CLEAR_TASK:需要与FLAG_ACTIVITY_NEW_TASK结合使用,清除当前任务栈,然后打开新的Activity
3.FLAG_ACTIVITY_SINGLE_TOP:与singleTop效果一致
4.FLAG_ACTIVITY_CLEAR_TOP:与singleTask效果类似,但是不会走onNewIntent回调
3. taskAffinity(亲和性)
设置activity和任务栈的依附关系
每个Activity可以设置不同的taskAffinity,如果没有设置默认等于Application的taskAffinity,如果Application没有设置,则默认等于包名
需要配合其他属性使用才会生效
+singleTask(FLAG_ACTIVITY_NEW_TASK)
会创建新的任务栈
+allowTaskReparenting = true
当其他应用打开该Activity时,Activity会默认在应用的任务栈中,如果有相同的taskAffinity的任务栈到前台后,该Activity会迁移到该任务栈中。默认为false,不会迁移。
如果是不同的taskAffinity的,几时同一个应用也会出现多个任务栈在最近任务栏中
4. 生命周期
正常生命周期:onCreate->onStart(可见)->onResume(可交互)->onPause->onStop->onDestroy
Activity A启动Activity B生命周期是怎么走?
A.onPause->B.onCreate->B.onStart->B.onResume->A.onStop->B.onPause->A.onRestart->A.onStart->A.onResume->B.onStop->B.onDestory
2.1. 如果B是透明的Activity或者是DialogActivity 会有什么区别:A不会执行onStop, onRestart和onStartonSaveInstance 和 onRestoreInstance
2.1. onSaveInstance
回调时机:onPause->onStop->onSaveInstance
触发情景:1.HOME键 2.关闭屏幕 3.打开其他Activity 4.切换方向
2.2. onRestoreInstance
回调时机:onCreate->onStart->onRestoreInstance->onResume
触发情景:只有重建Activity之后才会调用
2.3. 原理:将每一个有ID的View,以它的ID为Key,状态为Value存储在一个哈希数组中,进行保存对于在onSaveInstanceState()与onPause()中的数据处理有什么区别?
onSaveInstanceState用于做一些临时状态的保存,而onPause用于持久化数据的保存home键之后,activity的生命周期是:onPause->onStop->onSaveInstance
4. Activity启动和显示流程(https://juejin.cn/post/6847902222294990862)
- Activity.startActivity
- Instrumentation.execStartActivity(调用binder)
- ATMS.startActivityAsUser(Android 10之前是AMS)
- ActivityStarter(根据intent等参数决定如何启动Activity)
- ActivityStack(pause上一个Activity,启动下一个Activity,包括白屏显示也是在这里)
- ActivityStackSupervisor(判断启动的Activity对应的进程是否启动)
- 如果进程启动了,则调用ApplicationThread(binder)回到APP,到14
- 如果进程没启动,则调用AMS启动进程
- 通过Zygote fork一个新的进程,通过反射创建ActivityThread
- ActivityThread.main创建Looper,创建ActivityThread,启动Looper
- ActivityThread.attach关联ApplicationThread和AMS,建立binder通信
- AMS(创建和绑定Application)
- AMS通过调用ApplicationThread这个binder回到APP
- Application通过mH(handler)回到ActivityThread.handleBindApplication,通过Instrumentation回调Application的attachBaseContext和onCreate(初始化ContentProvider也是在这里)
- 回到AMS中,启动根Activity
- 通过ActivityStackSupervisor调用realStartActivityLocked,通过ApplicationThread binder通信,返回ActivityThread创建Activity
5. Activity和Fragment
Fragment生命周期:
onAttach -> onCreate -> onCreateView -> onViewCreated -> onStart -> onResume -> onPause -> onStop -> onDestoryView -> onDestroy -> onDetach
onAttach: 当Fragment和Activity建立联系时回调
onCreateView: Fragment创建视图
onViewCreated: 在onCreateView之后调用,用于给子类创建自己独特的View
onDestroyView: Fragment销毁视图,与onCreateView相对应
onDetach: 当Fragment和Activity解除绑定
P.S.在replace或者是ViewPager中,如果Fragment视图被销毁一定会走onDestroyView,但是不一定会走onDestroy启动一个带有Fragment的Activity,他们的生命周期是怎样的?(参考)
调用顺序:
D/MainActivity: MainActivity:
D/MainActivity: onCreate: start
D/MainFragment: onAttach:
D/MainFragment: onCreate:
D/MainActivity: onCreate: end
D/MainFragment: onCreateView:
D/MainFragment: onViewCreated:
D/MainFragment: onActivityCreated:
D/MainFragment: onViewStateRestored:
D/MainFragment: onCreateAnimation:
D/MainFragment: onCreateAnimator:
D/MainFragment: onStart:
D/MainActivity: onStart:
D/MainActivity: onResume:
D/MainFragment: onResume:
- activity和fragment startActivityForResult有什么区别
androidx.fragment:1.3之后
Fragment.startActivityForResult
->FragmentManager.launchStartActivityForResult
->ActivityResultLauncher.launch(Fragment的requestCode在这里做了一个转换,使用的是Fragment独特的key去请求Activity,在Fragment的onActivityResult中再去做还原。而Fragment的requestCode在Activity的onActivityResult中requestCode是一样的。)
androidx.fragment:1.3之前
Fragment.startActivityForResult
->FragmentHostCallback.onStartActivityFromFragment
->FragmentActivity.startActivityFromFragment(在这里对Fragment的requestCode做编码运算,让它大于0xffff0000。之后在Fragment的onActivityResult中再去做还原。而Fragment的requestCode在Activity的onActivityResult中是编码后的requestCode。)
onActivityResult回调
启动Activity之后,会在ActivityThread启动dispatchActivityResult,这个会优先回到当前的Activity,然后执行它的super,然后到fragment
1.3之前通过FragmentController找到对应的fragment
1.3之后通过mActivityResultRegistry进行dispatchResult
startActivityForResult新方式:Activity/Fragment.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { onActivityResult(it) }
给Fragment传参数的时候,为什么要用arguments,而不用方法直接调用呢?
在修改配置引起的重绘中,如果用arguments系统会帮忙保存,而直接方法调用就可能会丢失Activity和Fragment之间的通信方式?(参考)
EventBus,Activity,接口回调,ViewModel,Result API
6. 其他
a启动b启动c,b死掉了,怎么把c的result传回a
使用FLAG_ACTIVITY_FORWARD_RESULT
进行参数传递,这个flag不能和startActivityForResult一起使用同时启动两个Activity,
TaskStackBuilder.startActivitys(Intent [] intents)
3.activity和application的context,startactivity有什么区别?
如果 Context is not an Activity,则通过 Context.startActivity()
的时候,必须加上一个 Intent.FLAG_ACTIVITY_NEW_TASK
标志。因为非 Activity环境启动Activity 的时候没有 Activity 栈,所以需要加上这个标志位新建一个栈。
另,application的context生命周期是整个应用的生命周期,activity的生命周期只是activity