该部分主要记录Activity,Service,BroadcastReceiver,ContentProvider的基本知识和使用,关于高级部分后续将来不知道哪天的哪天可能或许会再写一篇文章来记录
Activity
对于Activity
的地位不再过多叙述,是一个应用向外界展示信息所必须的一个组件。
生命周期
经典的生命周期图
关于各个周期:
onCreate()
Activity
被创建时首先调用。onStart()
Activity
界面出现时。onResume()
Activity
被完全显示,可以与用户交互时。onPause()
Activity
失去焦点但仍对用户可见,如显示了一个弹窗。onStop()
Activity
被其他Activity
完全遮挡,对用户不可见,如跳转到新的Activity
或者退出程序,直接锁屏。onDestory()
Activity
被销毁时调用。onRestart()
Activity
对象再次被启动时调用。
-
正常启动生命周期
onCreate()->onStart()->onResume()->activity runing->onPause()->onStop()->onDestory()
-
被遮挡但可见不可操作又取消遮挡
onPause()->activity stop->onResume()->activity runing
-
不可见变为可见
onPause()->onStop()->activity stop->onRestart()->onStart()->onResume()->activity runing
Activity示例代码
启动模式
-
standard
标准模式。
Activity
默认的启动模式,Activity
每次启动都会在栈顶创建一个新的Activity
实例。
如果Activity
已经位于栈顶,则Activity
启动时也将会重新创建新的实例。 -
singleTop
栈顶复用模式。
Activity
启动时判断其是否在栈顶,如果在栈顶则直接复用,并且回调onNewIntent()方法,不会再重新创建新的Activity
实例。
如果未处于栈顶则重新创建新的Activity
实例。 -
singleTask
栈内复用模式。
1.Activity
被首次创建时首先检测AndroidManifest.xml中相应<activity />
节点下的android:taskAffinity="..."
属性是否存在,如果不存在则在启动该Activity
的Activity
所在的任务栈上新建该Activity
,如果属性值存在并与某一任务栈相同则在该任务栈中新建该Activity
,如果属性名与已存在的任务栈都不相同则新建与属性名相同的任务栈并新建该Activity
。
2.Activity
非首次创建启动时检测活动栈中是否已存在Activity
实例,如果存在则直接复用并将其之上的所有Activity
实例全部出栈,并且回调onNewIntent()
方法,使该Activity
处于栈顶的位置,如果不存在则在栈顶创建新的Activity实例。 -
singleInstance
单实例模式。
该模式下Activity
会启动一个新的任务栈来管理Activity
实例,当从其他任务栈中启动该Activity
时,该Activity
所在的任务栈,将会转移到前台。
可以在不同的程序中共享一个Activity
异常状态
当系统资源配置发生改变或者内存不足时Activity
会被杀死。
-
系统配置发生改变
系统配置发生改变Activity
会被杀死重建,经典场景就是横竖屏切换的时候。
此时的生命周期状态转换:
onSaveInstanceState()->onStop()->onDestory()->onCreate()->onStart()->onRestoreInstanceState()->onResume()->activity runing
这里出现了两个方法
1.onSaveInstanceState()
当Activity被异常状态下终止时会调用该方法来将Activity
终止前的相关状态保存在Bundle中用来重建时恢复状态
2.onRestoreInstanceState()
当Activity被在异常状态下重建时回调该方法,该方法中的Bundle里保存了异常终止前Activity相关状态。
此时可以通过在AndroidManifestl.xml文件中相应的activity节点下配置android:configChanges="orientation|keyboardHidden"
属性来禁止相应的配置改变时activity的销毁重建。但是此时会回调Activity中的onConfigurationChanged()
方法。 -
系统内存不足
当系统内存不足时,系统将会根据activity优先级的高低,优先杀死优先级低的Activity
。
1.此时的生命周期:
activity runing->onPause()->onStop()->onDestory()
2.优先级:
前台Activity
>可见非前台Activity
>后台Activity
Service
Service
是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行。
生命周期
service_lifecycle.png由上图可知
Service
有两种生命周期,分别对应着Service
的两种形式
Service形式
启动形式
如果应用组件通过startService()
方法来启动服务时,该服务即处于启动状态。
服务处于启动状态后将开始在后台无期限运行,组件被销毁也不会影响服务的运行状态。并且启动形式的服务与组件之间没有很大的关联并不会将服务结果返回给组件。如通过启动一个服务来下载网络资源。
启动的服务可以在组件中通过stopService()
或者在服务内部通过stopSelf()
方法来停止服务。
onCreate()
服务首次被创建时,系统将会调用该方法来进行相关设置。该方法只有在服务被创建时调用,如果服务已在运行,则该方法不会调用。
onStartCommand()
组件通过调用startService()
方法启动服务时,该方法将会被调用。该方法被调用后服务将会启动并将在后台无限期运行,并且需要调用stopService()
或者stopSelf()
方法来停止服务。每次调用startService()
方法都会该方法都将会被调用。在绑定状态下不需要实现这个方法
onDestory()
当服务不再使用并将被销毁时,系统将调用该方法。来清理所有的资源,如线程、监听器、接收器等。
onBind()
无论启动服务还是绑定服务该方法必须实现。如果组件通过bindSercie()
方法绑定服务,则系统将调用该方法,该方法的最后需要一个IBinder
接口的实现类,用来供组件与服务进行通信。如果组件通过startService()
方法来启动服务则该方法返回null
。
-
启动形式生命周期
onCreate()->onStartCommand()->Service runing->onDestroy()
启动形式服务示例代码
绑定形式
如果应用组件通过bindService()
方法绑定到服务时,该服务即处于绑定状态。组件与服务绑定后,绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信(IPC)跨进程执行这些操作。通俗来讲就是绑定服务后组件和服务就可以进行方法调用,增强两者之间的操作性。
组件与服务绑定后,服务开始运行,一个服务可以绑定多个组件,当绑定形式的服务与任何一个组件都失去绑定后该服务会被销毁。
绑定的服务可以在组件中通过stopService()
或者在服务内部通过stopSelf()
方法来停止服务。
onCreate()
服务首次被创建时,系统将会调用该方法来进行相关设置。该方法只有在服务被创建时调用,如果服务已在运行,则该方法不会调用。
onBind()
无论启动服务还是绑定服务该方法必须实现。如果组件通过bindSercie()
方法绑定服务,则系统将调用该方法,该方法的最后需要一个IBinder
接口的实现类,用来供组件与服务进行通信。如果组件通过startService()
方法来启动服务则该方法返回null
。
onUnbind()
绑定状态的服务被销毁时调用
onDestory()
当服务不再使用并将被销毁时,系统将调用该方法。来清理所有的资源,如线程、监听器、接收器等。
-
绑定形式生命周期
onCreate()->onBind()->Service runing->onUnbind()->onDestroy()
1、扩展Binder类实现绑定服务
2、使用AIDL来实现绑定服务
启动服务与绑定服务之间的转换问题
一个服务可以同时是启动状态和绑定状态。但是系统只会为一个Service创建一个实例对象,所以启动服务和绑定服务操作的都是同一个Service实例,但是由于两者的执行顺序不同将会出现下列两种情况:
-
先绑定服务后启动服务
状态变化:绑定服务模式->启动服务模式
绑定服务将会转换为启动服务运行,此时如果之前绑定服务的组件被销毁也不影响服务的运行。服务将会按照启动服务的模式运行。 -
先启动服务后绑定服务
状态变化:启动服务模式
服务不会转换为绑定服务,仍然以启动服务模式运行。
但是还是会与组件绑定,当与组件解除绑定之后,对服务无影响。
服务使用注意事项
注意:服务在其托管进程的主线程中运行,它既不创建自己的线程,也不在单独的进程中运行(除非另行指定)。 这意味着,如果服务将执行任何 CPU 密集型工作或阻止性操作(例如 MP3 播放或联网),则应在服务内创建新线程来完成这项工作。通过使用单独的线程,可以降低发生“应用无响应”(ANR) 错误的风险,而应用的主线程仍可继续专注于运行用户与 Activity 之间的交互。
由此可知服务是托管在进程的主线程中运行,所以如果服务要进行耗时或者阻塞性操作,则应该在服务内创建新的线程来完成工作。
-
建议使用:IntentService
IntentService
是继承并处理异步请求的一个类,在IntentService
内有一个工作线程来处理耗时操作
保证服务不被杀死
-
因内存资源不足被杀死
可将onStartCommand()
方法的返回值设为START_STICKY
或START_REDELIVER_INTENT
,该值表示服务在内存资源紧张时被杀死后,在内存资源足够时再恢复。
也可将Service
设置为前台服务,这样就有比较高的优先级,在内存资源紧张时也不会被杀掉。 -
用户通过 settings -> Apps -> Running -> Stop 方式杀死Service
该方法会执行Service
的生命周期将会调用onDestory
,所以可以在onDestory()
中发送广播重新启动Service
。
也可以开启两个服务,相互监听,相互启动。
onStartCommand返回值
-
START_STICKY
返回此值时Service
被系统kill后,系统将会尝试重新创建Service
,并调用onStartCommand()
方法,如果在此期间没有新的命令被传递到Service
则参数Intent
为null
-
START_NOTE_STICKY
返回值为该值时,如果Service
被系统kill则系统不会自动重启该服务 -
START_REDELIVEER_INTENT
返回此值时,如果Service
被系统kill杀死,系统将自动重启该服务,并重新传递Intent
-
START_STICKY_COMPATIBILITY
START_STICKY
的兼容版本并不保证kill后一定能重启
系统默认返回START_STICKY
网友评论