Activity
生命周期
onCreate():创建时调用
onStart():可见时调用
onResume():获取焦点时用
onPause():失去焦点时调用
onStop():不可见时调用
onDestory():销毁时调用
onRestart():重启时调用
一个AActivity跳转(启动)到一个BActivity中,生命周期的走动。点击Back返回呢。如果BActivity是透明的呢?如果BActivity是一个Dialog呢?
1)AonCreate -> AonStart -> AonResume -> AonPause -> BonCreate -> BonStart -> BonResume -> AonStop -> "Back" -> BonPause -> AonRestart -> AonStart -> AonResume -> BonStop -> BonDestory
2)BActivity是透明和BActivity是一个Dialog一样,A不执行onStop,所以也不用执行onRestart和onStart了,AonCreate -> AonStart -> AonResume -> AonPause -> BonCreate -> BonStart -> BonResume -> "Back" -> BonPause -> AonResume -> BonStop -> BonDestory
3)如果AActivity弹出的仅仅是个dialog则对生命周期没有影响
什么时候Activity单独走onPause()不走onStop()?
当 Activity 被另一个透明或者 Dialog 样式的 Activity 覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互,所以被覆盖的Activity并不会执行onStop()方法。
onPause与onStop的区别?
onPause():Activity失去焦点,但仍然可见。 onStop():Activity在后台,不可见(完全被另一个Activity挡住,或者程序后台运行)。
Activity调用finish()后怎么走到onDestroy的?
onPause -> onStop -> onDestory 或者 onPause -> (AonRestart -> AonStart ->) AonResume -> onStop -> onDestory
Dialog会不会影响Activity的生命周期,为什么?
生命周期回调都是 AMS 通过 Binder 通知应用进程调用的;而弹出 Dialog、Toast、PopupWindow 本质上都直接是通过 WindowManager.addView() 显示的(没有经过 AMS),所以不会对生命周期有任何影响。
Activity上有Dialog的时候按Home键时的生命周期
Dialog不影响Activity生命周期
前台切换到后台,然后再回到前台,Activity生命周期回调方法。
onPause -> onStop -> "回前台" -> onRestart -> onStart -> onResume
屏幕横竖屏切换时Activity的生命周期变化?是否了解onConfigurationChanged()。
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,
切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调
用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,
切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
Activity任务栈从底到顶为A-B-C,低内存杀死进程后,重新点击,显示哪个?这时如果C里面有Fragment是怎样恢复的?
先显示 ActivityC,Fragment 在 onCreate 里面恢复,通过反射空参构造函数进行创建,再把 Fragment add 到 Activity 上面。
View的绘制流程是从Activity的哪个生命周期方法开始执行的
onResume
Activity从后台进程切换到前台经历的生命周期
onRestart() -> onStart() -> onResume()
下拉状态栏是不是影响Activity的生命周期
不会
Activity是如何保存状态的?
见onSaveInstanceState
onSaveInstanceState()和onRestoreInstanceState()
onSaveInstanceState会被调用的时候:
- 当用户按下HOME键时。
- 从最近应用中选择运行其他的程序时。
- 按下电源按键(关闭屏幕显示)时。
- 从当前activity启动一个新的activity时。
- 屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。
onRestoreInstanceState(Bundle savedInstanceState)只有在activity确实是被系统回收,重新创建activity的情况下才会被调用。
Bundle是什么。Bundle里面都放一些什么东西?
装载数据,数据传输的容器。 k-v
启动模式
Activity启动模式及应用场景?
standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
singleTop:可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。
singleTask:只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。
singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。
taskaffinity
taskAffinity属性和Activity的启动模式息息相关,而且taskAffinity属性比较特殊,在普通的开发中也是鲜有遇到,但是在有些特定场景下却有着出其不意的效果。
taskAffinity是Activity在mainfest中配置的一个属性,暂时可以理解为:taskAffinity为宿主Activity指定了存放的任务栈[不同于App中其他的Activity的栈],为activity设置taskAffinity属性时不能和包名相同,因为Android团队为taskAffinity默认设置为包名任务栈。
taskAffinity只有和SingleTask启动模式匹配使用时,启动的Activity才会运行在名字和taskAffinity相同的任务栈中。
Activity的FLAG作用
FLAG_ACTIVITY_CLEAR_TOP : 等同于mainfest中配置的singleTask,没啥好讲的;
FLAG_ACTIVITY_SINGLE_TOP: 同样等同于mainfest中配置的singleTop;
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS: 其对应在AndroidManifest中的属性为android:excludeFromRecents=“true”,当用户按了“最近任务列表”时候,该Task不会出现在最近任务列表中,可达到隐藏应用的目的。
FLAG_ACTIVITY_NO_HISTORY: 对应在AndroidManifest中的属性为:android:noHistory=“true”,这个FLAG启动的Activity,一旦退出,它不会存在于栈中。
FLAG_ACTIVITY_NEW_TASK: 这个属性需要在被start的目标Activity在AndroidManifest.xml文件配置taskAffinity的值【必须和startActivity发其者Activity的包名不一样,如果是跳转另一个App的话可以taskAffinity可以省略】,则会在新标记的Affinity所存在的taskAffinity中压入这个Activity。
FLAG_ACTIVITY_CLEAR_TASK:如果Intent中设置了这个标志,会导致含有待启动Activity的Task在Activity被启动前清空。也就是说,这个Activity会成为一个新的root,并且所有旧的activity都被finish掉。这个标志只能与FLAG_ACTIVITY_NEW_TASK 一起使用。
启动流程
冷热启动
- 冷启动:当启动该Activity时,后台没有该Activity对应的应用的进程存在,这时Android系统会为该Activity创建对应进程,然后接着执行Activity创建和显示的流程,这个启动方式就是冷启动。其最主要的特点就是冷启动因为系统会通过zygote创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化目标Activity类(包括一系列的测量、布局、绘制),最后显示在界面上。
- 热启动:当启动目标Activity时候,Android后台已有该Activity对应的应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。该种启动方式最大的特点就是一个App应用从新进程的创建到进程的销毁,Application只会初始化一次,所以不必创建和初始化Application,直接走目标Activity的创建和显示(包括一系列的测量、布局、绘制)。
Activity的启动流程
Souruce端进程发送请求目标Activity启动阶段:
- Source端发起显示/隐式启动请求启动Activity
system_server进程通过AMS处理启动Activity请求:
-
解析启动目标Activity的Intent
-
创建目标Activity对应的ActivityRecord
-
为目标Activity查找/分配或者创建最优Task栈
-
Pause前台Activity
-
Resume请求的目标Activity
-
AMS请求zygote进程为目标Activity创建所属进程
zygote进程处理system_server进程发送的创建目标Activity进程请求阶段:
-
zygote接受AMS请求fork创建目标Activity所属进程
-
调用RuntimeInit,初始化目标进程运行环境
-
通过反射调用目标进程ActivityThread主线程main方法,开启目标进程新时代
目标Activity进程启动阶段:
-
开启目标Activity进程的的Looper消息循环
-
注册ApplicationThread到system_server进程
-
创建目标进程Application,并执行其onCreate方法
开启目标Activity生命周期阶段:
-
真正启动目的端Activity
-
通过反射加载目标Activity
-
执行目标Activity生命周期
-
初始化目标Activity窗口为显示做准备
目标Activity显示阶段:
-
新建DecorView
-
新建ViewRootImpl
20.将window添加到WMS准备显示
Source端Activity收尾工作:
- Source端Activity执行onStop()等逻辑
ApplicationThread、ActivityThread
Android应用ui是绘制在主线程中的,这个线程就是ActivityThread。但实际上看源码发现ActivityThread并没有继承自Thread,而是一个独立的类,只是在其main方法中开了一个Looper循环消息,不断接收处理发到主线程里面的消息,比如performLaunchActivity.
ApplicationThread也不是一个Thread,是一个Binder,主要用于应用进程和ActivityManagerService进程间通信的。整个ActivityThread框架是基于Binder通信的C/S结构,从图可知Server端是ActivityThread、ApplicationThread,Client是AMS(ActivityManagerService),而ApplicationThreadProxy可以看作AMS中Server代表。
Fragment
Activity如何传参给Fragment?为什么用setArgument传参,而不是使用带有参数的构造器?
setArgument()
在于在某些异常情况下Fragment在销毁重建时其内部底层只会调用其无参构造,而导致有参数据丢失。我们在使用Fragment传值时,更推荐使用setArguments()来传数据。
关于Fragment操作的,管理Fragment的类叫什么,在Fragment中管理Fragment用什么?
FragmentManager,getSupportFragmentManager()获得。
说一下FragmentA启动了FragmentB,FragmentB中按下返回键只退出FragmentB怎么实现。
www.demodashi.com/demo/15724.…
- 在MainActivity中声明一个返回键处理的接口
- 然后在MainActivity 中重写返回键功能,判断fragment中是否设置了监听器
- 在FragmentB中实现OnFragmentBackListener接口
- 在FragmentB的setListener中设置监听,onDestroyView()中销毁监听,然后在onbackForward()中做Fragment的返回键处理。
Fragment生命周期
onAttach():和宿主Activity建立关联时调用
onCreate():创建时调用
onCreateView():加载Fragment的布局时调用
onActivityCreated():宿主Activity创建完毕时调用
onStart():可见时调用
onResume():获取焦点时用
onPause():失去焦点时调用
onStop():不可见时调用
onDestoryView():移除Fragment的布局时调用
onDestory():销毁时调用
onDetach():与宿主Activity解除关联时调用
Fragment懒加载怎么实现?
setUserVisibleHint已弃用
- 为FragmentPagerAdapter的构造函数 添加参数
FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT - 封装一个BaseFragment:通过它的onReseume()方法来控制具体每个fragment的数据懒加载
- 继承并重写loadData方法
Fragment的ViewModel如何访问到Activity的ViewModel的数据
fragment从activity的viewmodel取数据再存到自己的viewmodel
Activity和Fragment数据交互(数据传递)
- Bundle
- 接口
- 广播
- 文件
- ViewModel?
通信
Activity之间的通信方式,如何传递数据
- Intent
- 借助类的静态变量
- 借助全局变量/Application
- 借助外部工具
– 借助SharedPreference,MMKV
– 使用Android数据库SQLite
– 赤裸裸的使用File
– Android剪切板 - 借助Service
- 单例对象
- EventBus
如果需要在Activity间传递大量的数据怎么办?
序列化
Activity和Service通信
binder
Intent
Intent显示跳转与隐式跳转,如何使用?
- 显示跳转:包名类名启动
- 隐式跳转: setAction,隐式跳转需要注意清单文件属性的配置
其他
一个应用打开了多个Activity,怎么安全关闭。
每次打开在application中的全局变量做纪录,关闭时循环关闭
Activity设置成为窗口。
修改主题,指定大小
问Activity中创建一个死循环任务线程,触发onDestroy后,如果会如何?
死循环任务线程继续执行
如何实现Activity窗口快速变暗
做一个属性动画的window
说下 Activity 跟 window,view 之间的关系?
- 在Activity中调用attach,创建了一个Window
- 创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
- 在Activity中调用setContentView(R.layout.xxx)
- 其中实际上是调用的getWindow().setContentView()
- 调用PhoneWindow中的setContentView方法
- 创建ParentView: 作为ViewGroup的子类,实际是创建的DecorView(作为FramLayout的子类)
- 将指定的R.layout.xxx进行填充 通过布局填充器进行填充【其中的parent指的就是DecorView】
- 调用到ViewGroup
- 调用ViewGroup的removeAllView(),先将所有的view移除掉 10.添加新的view:addView()
Service
两种Service类型:Service和IntentService
Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR
IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。在开发时只需要直接重写 onHandleIntent()方法,当开启服务之后系统会自动调用此方法来处理请求。
Service的两种启动方式以及生命周期:startService和bindService
- startService()方式启动时的生命周期回调方法 (1)启动服务startService : –>onCreate()–> onStart()
(2)停止服务stopService : –>onDestroy()
如果调用者直接退出而没有停止Service,则Service 会一直在后台运行。这里的退走只是关闭了UI界面。 startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方 法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用 startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用 startService()方法启动的服务,只能调用stopService()方法结束服务,服务结束时 会调用生命周期的onDestroy()方法。
- bindService()方式启动时的生命周期回调方法 (1)绑定bindService : –> onCreate() –> onBind()
(2)解绑unbindService: –>onUnbind() -> onDestroy()
正常停止程序服务的方法是先解绑unbindService,再停止服务stopService。如果绑定后调用stopService 方法,这时是不能停止服务的,如果这时再调用解绑unbindService,程序后先解绑,后停止服务。
startService和bindService分别适合应用在什么场景
startService
后台服务长期进行某项任务
bindService
短暂的使用
startService+bindService
如果想启动一个后台服务长期进行任务,且这个过程中需要与调用者进行交互,那么可以两者同时使用
比如,在下载的过程中(startService,做耗时操作)监听进度到界面上显示(bindService,通过ServinceConnection传递到Activity).
对于既使用startService,又使用bindService的情况,结束服务时需要注意的事项:
Service的终止,需要unbindService和stopService都调用才行;
当内存不足时Service被杀死了,如何重启这个Service
见onStartCommand的返回值有什么作用
onStartCommand的返回值有什么作用
怎么保证Service不被杀死/进程保活?
前台进程,IntentService优先级比Service高,因为是单独的线程,也有很多其他的方案
Service和Thread的区别?
Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR
IntentService能用bind方式启动吗?
不建议使用bindService去启动,如果用了,onHandleIntent根本不会调用,和启动一个普通的Service没两样。
问Service的启动过程?
ServiceManager
WindowMangerService
SystemService
Broadcast
可以再onReceive中开启线程么,会有什么问题?
在Activity已经退出、BroadcastReceiver已经结束的情况下,此时它们所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存时可能会优先终止该进程。如果宿主进程被终止,那么该进程内的所有子线程也会被中止,这样就可能导致子线程无法执行完成.。
两个应用同时注册一个广播,优先级都一样,哪个会先收到广播?
随机
有序广播
发送出去的广播被广播接收者按照先后顺序接收,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,且优先级(priority)高的广播接收器会先收到广播消息。有序广播可以被接收器截断使得后面的接收器无法收到它
ContentProvider
个人吐槽:它配Android四大组件吗,进程通信用AIDL不就好了。
Context
Application、Activity、Service中context的区别?能否启动一个Activity、Dialog?
blog.csdn.net/qq475703980…
NO1: 表示Application context的确可以开始一个Activity,但是它需要创建一个新的task。这可能会满足一些特定的需求,但是在你的应用中会创建一个不标准的回退栈(back stack),这通常是不推荐的或者不是是好的实践。
NO2: 表示这是非法的,但是这个填充(inflation)的确可以完成,但是是使用所运行的系统默认的主题(theme),而不是你app定义的主题。