Tip---Android的Service相关知识提炼

61 阅读5分钟

##异步消息处理基本用法

  1. 准备int常量用于标记某个任务

  2. 主线程实例化Handler对象, 同时重写HandlerhandleMessage()方法, 方法中通过使用if或者switch, 将(子线程发送的)Messagewhat字段 同一个或者以上的int任务标志常量做匹配, 调用对应的任务处理模块进行处理;

  3. 在对应的场景(如某个View的回调方法中): 利用匿名类的方式,通过Thread、Runnable()、run()、start()等类与方开启子线程,在子线程的线程任务执行单位(即run())中:  3.1. 实例化Message对象;  3.2. 将任务常量id设置到Message实例对象的what字段中;  3.3. 使用2.中定义的Handler实例调用sendMessage()Message实例发送到MQ; 至此完成;

##Service生命周期 onCreate():服务第一次被创建时调用 onStartComand():服务启动时调用 onBind():服务被绑定时调用 onUnBind():服务被解绑时调用 onDestroy():服务停止时调用

##普通Service(开启Service的两个基本方法,其一)

  1. 新建一个类并令其继承Service且必须重写onBind()方法, 有选择的重写onCreate()、onStartCommand()onDestroy()方法;

  2. 在配置文件中进行注册;或者直接按照以下方法则AS会自动注册:

  3. 在对应的场景(如某个View的回调方法中), 利用Intent可实现Service的启动:

 Intent intent = new Intent(this, MyService.class);// MyService是刚刚定义好的Service
 startService(intent);

Service的停止:

Intent intent = new Intent(this, MyService.class);
stopService(intent);

##Service与Activity的通信(开启Service的两个基本方法,其二)

  1. 新建一个类(如MyService)继承自Service注册好;

  2. 类中定义一个内部类(如MyBinder)继承Binder, 在其内部编写要放在Service后台服务执行的逻辑方法模块;

  3. 继承自Service类(MyService)中 实例化继承Binder的内部类(MyBinder)实例 并作为MyService的成员变量;

  4. 重写onBind()方法,返回成员变量MyBinder实例

  5. 在对应启动Service活动中, 在活动中实例化一个ServiceConnection类对象, 并重写它的onServiceConnection()onServiceDisconnection()方法, 这两个方法分别会在活动与服务 成功绑定以及解除绑定的时候调用。 在onServiceConnected()方法中, 又通过向下转型得到了MyBinder的实例, 有了它就可以在活动中调用MyBinder中的任何非private方法了, 即实现Service与Activity的通信

  6. 最后在在对应的场景(如某个View的回调方法中), 利用Intent对象以及下面两个方法 实现活动和服务的绑定和解绑:

  • bindService()实现绑定, 它接收三个参数(Intent对象,ServiceConnection对象,标志位), 这里传入BIND_AUTO_CREATE 表示在活动和服务进行绑定后自动创建服务
  • unbindService()实现解绑, 传入ServiceConnection对象即可。

##前台Service 前台Service类似通知, 只不过在构建好一个Notification之后, 不需要NotificationManager将通知显示出来, 而是调用了startForeground()方法。

可以在新建的继承Service的类的onCreate()方法中,如下编写:

启动方法同普通Service,即在对应的场景(如某个View的回调方法中)编写:

 Intent intent = new Intent(this, MyService.class);// MyService是刚刚定义好的Service
 startService(intent);

##系统Service 除了自定义一个Service,可以使用现有的系统服务; 通过getSyetemService()方法并传入一个Name 即可得到相应的服务对象, 常用的系统服务如下表:

######下面学习AlarmManager系统服务,实现一个后台定时任务 调用AlarmManagerset()方法就可以设置一个定时任务set()三个参数(工作类型,定时任务触发的时间,PendingIntent对象): 1)工作类型:有四个值可选:

2)定时任务触发的时间:以毫秒为单位,传入值第一个参数对应关系: 3)PendingIntent对象: 一般会调用它的getBroadcast()方法来获取一个能够执行广播的PendingIntent。 这样当定时任务被触发的时候, 广播接收器中的onReceive()方法即可得到执行, 在onReceive()方法我们可以再次启动Service, 同时编写任务执行代码块;

实战使用时, 可以在新建的继承Service的类的onStartCommand()方法中, 如下编写: 注意这里的提供给PendingIntentIntent 跳转到的广播接收器是需要我们自己定义的, 这里定义的接收器是MyBroadcast 如此一来, 一旦启动MyService, 就会在onStartCommand()方法里设定一个定时任务10秒MyReceiveronReceive()方法将被回调执行, 紧接着又反过来启动MyService,反复循环。 从而实现一个能长期在后台进行定时任务的服务。 同时在MyReceiveronReceive()方法中 我们可以添加编写任务执行代码块

另外,从Android 4.4版本开始, 由于系统在耗电性方面进行了优化使得Alarm任务的触发时间会变得不准确。 如果一定要求Alarm任务的执行时间精确, 把AlarmManagersetExact()方法替代set()方法就可以了。

##IntentService 使用Android提供的IntentService, 可以简单地实现一个异步的、会自动停止的服务;

  1. 新建类并继承IntentService, 类中提供一个无参的构造函数 且必须在其内部调用父类的有参构造函数; 然后重写onHandleIntent()方法, 里面可以处理一些耗时操作而不用担心 ANR的问题, 因为这个方法已经是在子线程中运行的了。
  2. 在配置文件中进行注册。
  3. 在活动中利用Intent启动IntentService,同普通Service

实战参考:

onHandleIntent()方法中为了证实这个方法确实已经在子线程中, 打印了当前线程的id与稍后与主线程的线程id作对比。

另外,IntentService的特性是在运行结束后应该是会自动停止, 这里重写onDestroy()方法在其中打印一行日志, 证实服务是不是停止掉了。

接着注册:或者直接按照以下方法则AS会自动注册:在对应的场景(如某个View的回调方法中), 利用Intent可实现Service的启动,同普通Service在这里打印了主线程的 id, 用于同方才说的IntentServiceonHandleIntent()方法中打印的线程id进行对比;





参考学习笔记| AS入门(十) 组件篇之Service