目录
(一)Android基础
1)四大组件?
2)Activity和Fragment的生命周期?
3)Activity的四种启动模式对比?
4)Activity在有Dialog时按Home键的生命周期?
5)两个Activity 之间跳转时必然会执行的是哪几个方法?
6)Service的启动方法与生命周期?
7)广播分为哪几种,应用场景是什么?
8)广播的两种注册方式有什么区别?
9)广播发送和接收的原理?
10)Android Binder机制是做什么的,为什么选用Binder?
参考:
Activity【活动】:用于表现功能。
Service【服务】:后台运行服务,不提供界面呈现。
BroadcastReceiver【广播接收器】:用来接收广播。
Content Provider【内容提供商】:支持在多个应用中存储和读取数据,相当于数据库。
Activity生命周期图
Fragment生命周期图
Activity和Fragment生命周期对比图
Standard:
标准的启动模式,如果需要启动一个activity就会创建该activity的实例。也是activity的默认启动模式。
SingeTop:
如果启动的activity已经位于栈顶,那么就不会重新创建一个新的activity实例。而是复用位于栈顶的activity实例对象。如果不位于栈顶仍旧会重新创建activity的实例对象。
SingleTask:
设置了singleTask启动模式的activity在启动时,如果位于activity栈中,就会复用该activity,这样的话,在该实例之上的所有activity都依次进行出栈操作,即执行对应的onDestroy()方法,直到当前要启动的activity位于栈顶。一般应用在网页的图集,一键退出当前的应用程序。
SingleInstance:
如果使用singleInstance启动模式的activity在启动的时候会复用已经存在的activity实例。不管这个activity的实例是位于哪一个应用当中,都会共享已经启动的activity的实例对象。使用了singlestance的启动模式的activity会单独的开启一个共享栈,这个栈中只存在当前的activity实例对象。
当我们的Activity上弹出Dialog对话框时,程序的生命周期依然是onCreate() ---> onStart() ---> onResume(),在弹出Dialog的时候并没有onPause()和onStop()方法。而在此时我们按下Home键,才会继续执行onPause()和onStop()方法。这说明对话框并没有使Activity进入后台,而是在点击了Home键后Activity才进入后台工作。
原因就是,其实Dialog是Activity的一个组件,此时Activity并不是不可见,而是被Dialog组件覆盖了其他的组件,此时我们无法对其他组件进行操作而已。
首先定义两个Activity,分别为A和B。
当我们在A中激活B时,A调用onPause()方法,此时B出现在屏幕时,B调用onCreate()、onStart()、onResume()。
这个时候B【B不是一个透明的窗体或对话框的形式】已经覆盖了A的窗体,A会调用onStop()方法。
首先Service有两种启动方式,而在这两种启动方式下,它的生命周期不同。
Service启动方法:
Service生命周期:
普通广播:调用sendBroadcast()发送,最常用的广播。
有序广播:调用sendOrderedBroadcast(),发出去的广播会被广播接受者按照顺序接收,广播接收者按照Priority属性值从大-小排序,Priority属性相同者,动态注册的广播优先,广播接收者还可以选择对广播进行截断和修改。
静态注册:常驻系统,不受组件生命周期影响,即便应用退出,广播还是可以被接收,耗电、占内存。
动态注册:非常驻,跟随组件的生命变化,组件结束,广播结束。在组件结束前,需要先移除广播,否则容易造成内存泄漏。
继承BroadcastReceiver,重写onReceive()方法。
通过Binder机制向ActivityManagerService注册广播。
通过Binder机制向ActivityMangerService发送广播。
ActivityManagerService查找符合相应条件的广播(IntentFilter/Permission)的BroadcastReceiver,将广播发送到BroadcastReceiver所在的消息队列中。
BroadcastReceiver所在消息队列拿到此广播后,回调它的onReceive()方法。
做什么?
Android Binder是用来做进程通信的,Android的各个应用以及系统服务都运行在独立的进程中,它们的通信都依赖于Binder。
为什么?
为什么选用Binder,我们知道Android也是基于Linux内核,Linux现有的进程通信手段有以下几种:
管道:在创建时分配一个page大小的内存,缓存区大小比较有限;
消息队列:信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信;
共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决;
套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信;
信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。6. 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等;
既然有现有的IPC方式,为什么重新设计一套Binder机制呢。主要是出于以上三个方面的考量:
高性能:从数据拷贝次数来看Binder只需要进行一次内存拷贝,而管道、消息队列、Socket都需要两次,共享内存不需要拷贝,Binder的性能仅次于共享内存。
稳定性:上面说到共享内存的性能优于Binder,那为什么不适用共享内存呢,因为共享内存需要处理并发同步问题,控制负责,容易出现死锁和资源竞争,稳定性较差。而Binder基于C/S架构,客户端与服务端彼此独立,稳定性较好。
安全性:我们知道Android为每个应用分配了UID,用来作为鉴别进程的重要标志,Android内部也依赖这个UID进行权限管理,包括6.0以前的固定权限和6.0以后的动态权限,传荣IPC只能由用户在数据包里填入UID/PID,这个标记完全是在用户空间控制的,没有放在内核空间,因此有被恶意篡改的可能,因此Binder的安全性更高。