Android知识点整理-四大组件

904 阅读15分钟

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则对生命周期没有影响

blog.csdn.net/u013700040/…

什么时候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 上面。

juejin.cn/post/684490…

View的绘制流程是从Activity的哪个生命周期方法开始执行的

onResume

Activity从后台进程切换到前台经历的生命周期

onRestart() -> onStart() -> onResume()

下拉状态栏是不是影响Activity的生命周期

不会

Activity是如何保存状态的?

见onSaveInstanceState

onSaveInstanceState()和onRestoreInstanceState()

onSaveInstanceState会被调用的时候:

  1. 当用户按下HOME键时。
  2. 从最近应用中选择运行其他的程序时。
  3. 按下电源按键(关闭屏幕显示)时。
  4. 从当前activity启动一个新的activity时。
  5. 屏幕方向切换时(无论竖屏切横屏还是横屏切竖屏都会调用)。

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 一起使用。

启动流程

image.png blog.csdn.net/tkwxty/arti…

冷热启动

  1. 冷启动:当启动该Activity时,后台没有该Activity对应的应用的进程存在,这时Android系统会为该Activity创建对应进程,然后接着执行Activity创建和显示的流程,这个启动方式就是冷启动。其最主要的特点就是冷启动因为系统会通过zygote创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化目标Activity类(包括一系列的测量、布局、绘制),最后显示在界面上。
  2. 热启动:当启动目标Activity时候,Android后台已有该Activity对应的应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。该种启动方式最大的特点就是一个App应用从新进程的创建到进程的销毁,Application只会初始化一次,所以不必创建和初始化Application,直接走目标Activity的创建和显示(包括一系列的测量、布局、绘制)。

Activity的启动流程

Souruce端进程发送请求目标Activity启动阶段:

  1. Source端发起显示/隐式启动请求启动Activity

system_server进程通过AMS处理启动Activity请求:

  1. 解析启动目标Activity的Intent

  2. 创建目标Activity对应的ActivityRecord

  3. 为目标Activity查找/分配或者创建最优Task栈

  4. Pause前台Activity

  5. Resume请求的目标Activity

  6. AMS请求zygote进程为目标Activity创建所属进程

zygote进程处理system_server进程发送的创建目标Activity进程请求阶段:

  1. zygote接受AMS请求fork创建目标Activity所属进程

  2. 调用RuntimeInit,初始化目标进程运行环境

  3. 通过反射调用目标进程ActivityThread主线程main方法,开启目标进程新时代

目标Activity进程启动阶段:

  1. 开启目标Activity进程的的Looper消息循环

  2. 注册ApplicationThread到system_server进程

  3. 创建目标进程Application,并执行其onCreate方法

开启目标Activity生命周期阶段:

  1. 真正启动目的端Activity

  2. 通过反射加载目标Activity

  3. 执行目标Activity生命周期

  4. 初始化目标Activity窗口为显示做准备

目标Activity显示阶段:

  1. 新建DecorView

  2. 新建ViewRootImpl

20.将window添加到WMS准备显示

Source端Activity收尾工作:

  1. 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() image.png 在于在某些异常情况下Fragment在销毁重建时其内部底层只会调用其无参构造,而导致有参数据丢失。我们在使用Fragment传值时,更推荐使用setArguments()来传数据。

关于Fragment操作的,管理Fragment的类叫什么,在Fragment中管理Fragment用什么?

FragmentManager,getSupportFragmentManager()获得。

说一下FragmentA启动了FragmentB,FragmentB中按下返回键只退出FragmentB怎么实现。

www.demodashi.com/demo/15724.…

  1. 在MainActivity中声明一个返回键处理的接口
  2. 然后在MainActivity 中重写返回键功能,判断fragment中是否设置了监听器
  3. 在FragmentB中实现OnFragmentBackListener接口
  4. 在FragmentB的setListener中设置监听,onDestroyView()中销毁监听,然后在onbackForward()中做Fragment的返回键处理。

Fragment生命周期

image.png

onAttach():和宿主Activity建立关联时调用
onCreate():创建时调用
onCreateView():加载Fragment的布局时调用
onActivityCreated():宿主Activity创建完毕时调用
onStart():可见时调用
onResume():获取焦点时用
onPause():失去焦点时调用
onStop():不可见时调用
onDestoryView():移除Fragment的布局时调用
onDestory():销毁时调用
onDetach():与宿主Activity解除关联时调用

Fragment懒加载怎么实现?

setUserVisibleHint已弃用

  1. 为FragmentPagerAdapter的构造函数 添加参数FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
  2. 封装一个BaseFragment:通过它的onReseume()方法来控制具体每个fragment的数据懒加载
  3. 继承并重写loadData方法

Fragment的ViewModel如何访问到Activity的ViewModel的数据

fragment从activity的viewmodel取数据再存到自己的viewmodel

Activity和Fragment数据交互(数据传递)

  1. Bundle
  2. 接口
  3. 广播
  4. 文件
  5. 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 之间的关系?

image.png

  1. 在Activity中调用attach,创建了一个Window
  2. 创建的window是其子类PhoneWindow,在attach中创建PhoneWindow
  3. 在Activity中调用setContentView(R.layout.xxx)
  4. 其中实际上是调用的getWindow().setContentView()
  5. 调用PhoneWindow中的setContentView方法
  6. 创建ParentView:
作为ViewGroup的子类,实际是创建的DecorView(作为FramLayout的子类)
  7. 将指定的R.layout.xxx进行填充
通过布局填充器进行填充【其中的parent指的就是DecorView】
  8. 调用到ViewGroup
  9. 调用ViewGroup的removeAllView(),先将所有的view移除掉 10.添加新的view:addView()

Service

两种Service类型:Service和IntentService

Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR

IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。在开发时只需要直接重写 onHandleIntent()方法,当开启服务之后系统会自动调用此方法来处理请求。

Service的两种启动方式以及生命周期:startService和bindService

image.png

  1. startService()方式启动时的生命周期回调方法 (1)启动服务startService : –>onCreate()–> onStart()

(2)停止服务stopService : –>onDestroy()

如果调用者直接退出而没有停止Service,则Service 会一直在后台运行。这里的退走只是关闭了UI界面。 startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方 法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用 startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用 startService()方法启动的服务,只能调用stopService()方法结束服务,服务结束时 会调用生命周期的onDestroy()方法。

  1. 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的返回值有什么作用

www.cnblogs.com/mjtabu/p/12…

怎么保证Service不被杀死/进程保活?

前台进程,IntentService优先级比Service高,因为是单独的线程,也有很多其他的方案

Service和Thread的区别?

Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR

IntentService能用bind方式启动吗?

不建议使用bindService去启动,如果用了,onHandleIntent根本不会调用,和启动一个普通的Service没两样。

问Service的启动过程?

blog.csdn.net/u012165769/…

ServiceManager

WindowMangerService

SystemService

Broadcast

可以再onReceive中开启线程么,会有什么问题?

在Activity已经退出、BroadcastReceiver已经结束的情况下,此时它们所在的进程就变成了空进程(没有任何活动组件的进程),系统需要内存时可能会优先终止该进程。如果宿主进程被终止,那么该进程内的所有子线程也会被中止,这样就可能导致子线程无法执行完成.。

两个应用同时注册一个广播,优先级都一样,哪个会先收到广播?

随机

有序广播

发送出去的广播被广播接收者按照先后顺序接收,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,且优先级(priority)高的广播接收器会先收到广播消息。有序广播可以被接收器截断使得后面的接收器无法收到它

ContentProvider

个人吐槽:它配Android四大组件吗,进程通信用AIDL不就好了。

Context

Application、Activity、Service中context的区别?能否启动一个Activity、Dialog?

blog.csdn.net/qq475703980… image.png NO1: 表示Application context的确可以开始一个Activity,但是它需要创建一个新的task。这可能会满足一些特定的需求,但是在你的应用中会创建一个不标准的回退栈(back stack),这通常是不推荐的或者不是是好的实践。

NO2: 表示这是非法的,但是这个填充(inflation)的确可以完成,但是是使用所运行的系统默认的主题(theme),而不是你app定义的主题。