Activity
Activity生命周期
生命周期:onCreate()
-> onStart()
- > onResume()
-> onPause()
-> onStop()
-> onDestroy()
特殊的生命周期
资源相关的系统配置发生改变会导致 activity 被杀死并重新创建。系统配置发生改变以后,activity 会销毁,其 onPause、onStop、onDestroy 会相继执行,因为是异常销毁,系统会调用 onSaveInstanceState 来保存 activity 当前状态,这个方法的调用时机是在 onStop 之前,与 onPause 无时序关系。activity 重建后会调用 onRestoreInstanceState,并且把销毁时 onSaveInstance 保存的 Bundle 对象作为参数同时传递给 onRestoreInstance 和 onCreate,onRestoreInstance 在 onStart 方法之后回调。同时,onRestoreInstance 方法会自动帮我们做一些恢复工作。另外,和 activity 一样,每个 view 都有自己相关的 onSaveInstanceState 方法和 onRestoreInstanceState 方法。
应用场景:假设 Activity A 位于栈顶,从 A 跳转 B 时声明周期
当用户点击A中按钮来到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。
此时如果点击Back键,将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。
Activity 启动模式
standard - 默认模式
默认的启动模式,既标准模式,在不指定启动模式的前提下,系统默认使用该模式启动 Activity,每次启动一个 Activity 都会重写一个新的实例,不管这个实例存在不存在。该 Activity 属于启动它的 Activity 所在的任务占中。
应用场景:默认。
singleTop - 栈顶复用模式
该模式下,当前栈中已存在该 Activity 实例并且该实例位于栈顶,则不会重新创建 Activity 的实例,而是复用栈顶的实例,并且将 Intent 对象传入,回调 onNewIntent 方法。其余情况,与 standard 模式相同,会重新创建实例。
应用场景:登录页面、WXPayEntryActivity、WXEntryActivity 、推送通知栏。
singleTask - 栈内复用模式
该模式下,如果栈中存在这个 Activity 的实例就会复用这个 Activity,不管它是否位于栈顶,复用时,会将它上面的 Activity 全部出栈,并且会回调该实例的 onNewIntent 方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过 taskAffinity 属性指定。如果这个任务栈不存在,则会创建这个任务栈。
应用场景:应用主页面、WebView页面、扫一扫页面、电商中:确认订单页面,付款页面。
singleInstance - 全局唯一模式
该模式具备 singleTask 模式的所有特性,并且这种模式下的 Activity 会单独占用一个 Task 栈,具备全局唯一性,即整个系统中只有一个实例。由于栈内复用的特性,后续的请求不会创建新的 Activity 实例,除非这个特殊的任务栈被销毁。以 singleInstance 模式启动的 Activity 在整个系统中是单利的,如果启动这样的 Activity 时已经存在一个实例,那么会把它所在的任务调度到前台,重用这个实例。
应用场景:系统 Launcher、锁屏键、来电显示等系统应用。
TaskAffinity 属性
任务相关性。
- 这个参数标识了一个 Activity 所需任务栈的名字。默认情况下,所有 Activity 所需的任务战的名字为应用的包名。
- 每个 Activity 的 taskAffinity 值都可以被指定,用来覆盖其默认值。
- 通常来说,具有相同 taskAffinity 的 Activity 属于同一个任务。
- 当设置一个 Activity 的 taskAffinity 属性为空字符串时,表明这个 Activity 不属于任何 task。
- taskAffinity 属性不对 standard 和 singleTop 模式有任何影响,这两种模式下不会创建新的 task(如果不指定默认值,即包名)。
Activity 与 Fragment 生命周期关系
创建过程:Fragment - onAttach -> Fragment - onCreate -> Fragment - onCreateView -> Activity - onCreate -> Fragment - onActivityCreate -> Activity - onStart -> Fragment - onStart -> Activity - onResume -> Fragment - onResume
销毁过程:Fragment - onPause -> Activity - onPause -> Fragment - onStop -> Activity - onStop -> Fragment - onDestroyView -> Fragment - onDestroy -> Fragment - onDetach -> Activity - onDestroy
Activity 与 menu 创建先后顺序
在 Activity 创建完回调 onResume 后创建 menu,回调 onCreateOptionMenu。
Service
本地服务(LocalService)
调用者和service在同一个进程里,所以运行在主进程的main线程中。所以不能进行耗时操作,可以采用在service里面创建一个Thread来执行任务。service影响的是进程的生命周期,讨论与Thread的区别没有意义。
任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例。
启动方式:
start 方式启动服务
步骤:
1、定义一个类继承 service
2、清单文件中配置 service
3、使用 context 的 startService(Intent) 方法启动 service
4、不使用时,调用 stopService(Intent) 方法停止服务
生命周期:
onCreate() – > onStartCommand() – > onDestory()
注意:如果服务已经开启,不会重复回调onCreate()方法,如果再次调用context.startService()方法,service而是会调用onStart()或者onStartCommand()方法。停止服务需要调用context.stopService()方法,服务停止的时候回调onDestory被销毁。特点:
一旦服务开启就跟调用者(开启者)没有任何关系了。开启者不能调用服务里面的方法。
bind 方式启动服务
步骤:
定义一个类继承 service
清单文件中注册 service
使用 context 的 bindService(Intent,ServiceConnection,int) 方法启动 service
不再使用时,调用 unbindService(ServiceConnection) 方法停止该服务
生命周期:
onCreate() – > onBind() –> onUnbind() – > onDestory()
注意:
绑定服务不会调用 onStart 或者 onStartCommand 方法
特点:
bind 的方式启动服务,绑定服务,服务的生命周期跟随绑定者。绑定者可以调用服务里面的方法。
远程服务
调用者和 service 不再同一个进程中, service 在单独的进程中的 main 线程,是一种跨进程通信方式。
在服务的内部创建一个内部类,提供一个方法,可以间接调用服务的方法;
把暴露的接口文件的扩展名改为 .aidl 文件,去掉访问修饰符;
实现服务的 onbind 方法,继承 Bander 和实现 aidl 定义的接口,提供给外界可调用的方法
在 Activity 中绑定服务 bindService;
在服务成功绑定的时候回调 onServiceConnected 方法,床底一个 IBinder 对象
aidl 定义的接口 .Stub.asInterface(binder) 调用接口里面的方法
IntentService
IntentService 是 Service 的子类,比普通的 Service 增加了额外的功能。
Service 本身存在的两个问题:
- Service 不会专门启动一个单独的进程,Service 与它所在的应用位于同一个进程中;
- Service 也不是专门一条新进程,因此不应该在 Service 中直接处理耗时的任务
IntentService 特征:
- 会创建独立的 worker 线程来处理所有的 Intent 请求;
- 会创建独立的 worker 线程来处理 onHandleIntent 方法实现的代码,无需处理多线程问题;
- 所有请求处理完成后,IntentService 会自动停止,无需调用 stopSelf 方法停止;
- 为 Service 的 onBind 提供默认实现,返回 null;
- 为 Service 的 onStartCommand 提供默认实现,将请求的 Intent 添加到队列中。
BroadcastReceiver
广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;然而有序广播是按照接收者声明的优先级别(声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C。A得到广播后,可以往广播里存入数据,当广播传给B时,B可以从广播中得到A存入的数据。
发送广播
1 | Context.sendBroadcast() |
注意:BroadCastReceiver 生命周期很短,在 onReceiver 中需要进行耗时操作时,应该考虑在 Service 中开启一个新线程处理。
静态注册和动态注册区别
- 动态注册广播不是常驻型广播,也就是说广播跟随activity的生命周期。注意: 在activity结束前,移除广播接收器。
静态注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。 - 当广播为有序广播时:
1 优先级高的先接收
2 同优先级的广播接收器,动态优先于静态
3 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。 - 当广播为普通广播时:
1 无视优先级,动态广播接收器优先于静态广播接收器
2 同优先级的同类广播接收器,静态:先扫描的优先于后扫描的,动态:先注册的优先于后注册的。
小结:
- 在Android 中如果要发送一个广播必须使用sendBroadCast 向系统发送对其感兴趣的广播接收器中。
- 使用广播必须要有一个intent 对象必设置其action动作对象
- 使用广播必须在配置文件中显式的指明该广播对象
- 每次接收广播都会重新生成一个接收广播的对象
- 在BroadCastReceiver中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理
- 如果在AndroidManifest.xml中注册,当应用程序关闭的时候,也会接收到广播。在应用程序中注册就不产生这种情况了。
ContentProvider
contentprovider是android四大组件之一的内容提供器,它主要的作用就是将程序的内部的数据和外部进行共享,为数据提供外部访问接口,被访问的数据主要以数据库的形式存在,而且还可以选择共享哪一部分的数据。这样一来,对于程序当中的隐私数据可以不共享,从而更加安全。contentprovider是android中一种跨程序共享数据的重要组件。
原文:
https://blog.csdn.net/mynameishuangshuai/article/details/51491074