Service(服务) (服务不是实现耗时操作的,里面可以写耗时操作)
1. 什么是服务: Android中的四大组件, 是一个可以长时间在后台运行的不提供用户界面的一个类.
2.服务的特性: 服务一旦被启动无论启动它的界面还存不存在,服务都可以保持运行.
服务可以被别的组件绑定,用于和绑定者进行交互或者可以实现IPC(进程间)通信
3.什么时候需要在程序中添加服务: 当程序中有一些不需要用户界面的功能,但是程序没有界面打开的时候也可以实现这些功能,就需要在程序中添加服务. 如,执行和网络相关的操作(如,下载), 音乐的播放, 文件的操作(上传).
4.服务和线程的区别: 服务不是线程, 也不是用来执行耗时操作的(虽然可以把耗时操作放在服务中), 它是Android系统提供的用于把某些不需要的功能置于后台运行的容器.
5.服务的两种使用方式:
a, 启动的方式使用服务
当应用程序的别的组件(Activity)通过调用startService方法启动服务的时候, 这个服务就称为启动的服务.
启动的服务的特性: 无论启动者还存不存在, 服务都可以保持在后台长时间运行
启动的服务的使用场景:如果服务所执行的是比较简单一的操作, 并且这个操作是不需要给启动者返回结果, 就可以采用启动的方式使用服务 如单纯执行一个下载或者是上传的操作.
当启动的服务把功能执行完之后,应该把服务销毁掉.
b, 绑定的方式使用服务
当应用程序中的组件(Activity)通过调用bindService方法绑定服务的时候,这个服务就称为绑定的服务
绑定服务的使用场景: 当绑定者需要服务有交互的时候, 就可以采用绑定的方式使用服务. (如, 把音乐的播放放在服务中实现, 程序中还需要通过界面控制音乐的播放, 暂停等, 这个时候界面就需要和服务有交互, 就应该采用绑定的方式使用服务.)
绑定的服务的特性:仅仅在绑定者存在的时候, 绑定的服务才会存在, 当绑定者被销毁, 则绑定的服务也是会被销毁. 一个服务可以同时被多个绑定者绑定, 只有所有的绑定者全部被销毁, 服务才会被销毁.
c, 同时采用启动和绑定的方式使用: 首先先启动然后再绑定
使用场景: 如果程序中需要和服务有交互, 同时当界面退出的时候依旧希望服务能在后台继续保持运行, 则需要采用先启动在绑定.
6, 服务的使用是通过Intent. 服务运行在程序的主线程中, 故不可以在服务中执行耗时操作, 否则会造成ANR.
7, 在程序中添加Service需要首先创建Service子类, 在子类中需要重写一些方法:
onStartCommand() 当采用startService方式创建服务对象的时候, 服务中的该方法就被调用, 该方法被调用的时候就表示服务已经启动运行了.
该方法是定义服务功能的方法. 当采用bindService方法创建服务的时候, 该方法不会被调用
onBind() 仅仅在采用bindService方法创建服务的时候才会调用, 该方法的调用表示有绑定者要绑服务. 通过该方法给绑定者返回一个IBinder对象, 通过该对象实现绑定者和服务的交互.
onCreate() 在采用绑定的方式以及启动的方式使用服务的时候均会被调用, 该方法的调用表示服务对象被创建, 可以在该方法中实现对服务进行初始化的工作. 该方法仅仅在服务对象第一次被创建的时候调用[ 如果程序中的服务对象已经创建了, 再次创建该服务对象,则服务对象不会新建].
onDestroy() 采用启动或者是绑定的方式使用服务, 当服务被销毁该方法均会被调用, 该方法的调用就表示服务对象被销毁, 就应该在该方法中释放资源.
8, 采用启动的方式使用服务
a, 创建Service子类, 重写相关的生命周期方法
b, 在配置文件中注册创建的Service子类
c, 在Activity中调用Intent指明启动哪个服务
d, 在Activity 中调用 startService()方法按照启动的方式创建出服务对象
//采用绑定的方式使用服务才会调用的方法
public IBinder onBind(Intent intent){}
//当服务的对象被创建的时候, 该方法被调用
//该方法可以用于实现对服务的初始化
public void onCreate(){}
//采用启动的方式使用服务的时候才会被调用
//该方法的调用表示服务已经启动运行[定义服务的功能]
public int onStartConmmand(Intent intent , int flags, int startld){}
//当服务对象被销毁的时候被调用该方法
// 应该在该方法中实现对服务中所开辟的资源的释放
public void onDestroy(){}
//
9. 销毁采用启动方式创建的服务对象有两种方式: a, 在启动者中调用stopService方法 b,在Service中当Service把它的任务执行完之后在Service中调用stopService
列: Intent stopIntent =new Intent(this, MyService.class);
stopService(stopIntent);//销毁采用启动
10. 采用启动的方式创建Service的时候, Service的生命周期由3个方法构成:
onCreate() 表示服务对象被创建 该方法仅在服务对象新建的时候才会调用
onStartCommand() 表示服务启动运行
onDestroy() 表示服务对象被销毁
服务第一次新建生命周期的调用: onCreate() --->onStartCommand()
服务对象已经创建过, 反复的启动该服务, 声明周期的调用: 反复的调用onStartCommand()
通过stop相关的方法停止一个服务, 生命周期的执行: 直接调用onDestory()
//判断在那个线程运行;
Thread.currentThread().getName());
11. 服务运行于主线程中, 在服务中不能直接进行耗时操作.(如果需要在服务中执行耗时的操作,应该在服务中开辟子线程)
12. 借助于MediaPlayer理解Service的后台特性
用Activity播放音乐的特点: 当界面不退出音乐的播放和暂停都是正常. 如果在音乐播放的时候,退出了界面,当重新进入界面的时候音乐的播放和暂停都不在正常. 这种结果的原因: Activity是提供用于界面的前台组件,当退出界面的时候,当前的Activity就会被销毁, 当再次进入的界面的时候, 又会重新创建一个新的Activity, 伴随这个新的Activity的创建又会创建一个新的MediaPlayer, 在现在的界面在操作MediaPlayer的时候, 控制的就是第二个MediaPlayer对象.
如果无论界面有没有打开音乐的播放都能够进行, 同时界面打开关闭多少次, 再次打开的时候都能正常控制音乐的播放, 就需要通过服务实现
用Service播放音乐的可以实现后台播放, 界面再次打开依旧能够控制音乐的播放的原因: 采用启动的方式创建的Service在界面退出的时候不会被销毁,所以音乐依旧能在后台播放,同时因为Service没有被销毁, 所以再次打开界面的时候,操作的还是同一个服务对象, 该服务对象的MediaPlayer还是之前的MediaPlayer, 所以在控制音乐的播放操作的还是同一个MediaPlayer对象.
13. 当Android系统内存不够用的时候,系统会强制杀死一些服务对象以恢复系统资源[保留足够的内存保证Android系统本身的正常运行].当一个服务是被Activity绑定的, 如果该Activity处于前台运行则该服务被销毁的可能性比较小.如果一个服务仅仅是采用启动的方式创建,在后台运行,则这个服务被在系统内存不够的时候, 被系统杀死的可能性会比较高. 当一个服务因系统内存不够用而被系统强制销毁, 在系统的内存恢复的时候, 系统会重新的创建被它销毁的服务对象,在系统重新创建被销毁的服务对象的时候, 可以在程序中通过onStartCommand()方法的返回值告知系统如何重新创建被销毁的服务对象.
START_NOT_STICKY :(非粘性服务) 表示当前的服务对象因系统的内存不够而被杀死, 当系统的内存重新恢复的时候, 之前被杀死的服务对象是不会重新启动的.
START_STICKY: (粘性服务--->不带值) 表示当前的服务因为系统的内存不够被系统意外杀死之后, 在系统的内存重新恢复的时候, 之前因系统内存不够而被杀死的服务对象会被重新创建出来. 但是不会把最后一次启动服务的时候的Intent重新传入onStartCommand方法中.
START_REDELIVER_INTENT: (粘性服务-->带值) 表示当服务因为系统的内存不够而被杀死, 在系统的内存恢复的时候, 会重新创建之前因内存不够而被杀死的服务对象,同时会把之前最后一次启动服务的时候创建的Intent对象传入onStartCommand方法中.
14. IntentService
作用: 也是Service同样满足Service特性, 提供一个便捷的方式实现在Service中执行耗时的操作.
特点: 当服务的功能执行完毕之后, 该服务对象会自动销毁.