android开发官网对service的介绍的一点回顾:(这里讲的不全也不够详细,详见开发文档)
service主要是用来运行后台程序,不占有界面。
service分两种:
一 普通的service继承Service类,比较重要的方法有:
1 onCreate(),每次create的时候调用
2 onStartCommand ,每次客户程序(我自己想的个名词,其实就是activity,service或者broadcast等能发起startService等)调用startService时响应,不是每次startService都会调用onCreate()
3 onBind(),一个普通的service可以被start,也可以被bind,onBind()的时候不会触发onStart(),而是可以直接获取此service实例并调用其public方法,详见开发文档中onBind的使用方法。
4 普通service不会自动结束,需要手动的调用stopSelf()才能结束
注意:普通的service占用ui线程即主线程,在onCreate,onStartCommand 和onBind,以及onDestory()等方法中都会阻塞主线程,所以有时候可能会因为后台的service是的ui没有响应。解决这个问题的办法是把费时的操作放在新的线程中,可以自己新建一个线程,或者,采用下面将的IntentService。
二 IntentService
IntentService是为了方便开发者,提供的一个更方便的抽象类。
1 这个抽象类的特点是:
有一个worker 线程,按顺序执行每一个startService发送过来的intent,后发的intent在之前的intent被处理之前将会等待;
intentService的业务逻辑应该写在方法onHandleIntent中,这个方法不占用ui线程。
处理完所有的intent之后并且没有等待中的intent,此intentService将会自动销毁。所以用intentService可以发一个intent以后就不再管它了。
2 使用intentService不提倡重写普通service中提到的onCreate,onStartCommand ,onBind等方法,如果要重写,注意两点:这几个方法占用主线程,记得调用super.***()。
3 重要方法onHandleIntent
intentService的业务逻辑应该写在此方法中,如处理网络下载,写入文件等费时操作,可以不影响ui界面。同时执行完了以后如果需要通知ui界面,就需要从ui所在activity中bind到此service,并注册Handler以更新ui,提示service的操作已完成。
以上都是开发文档中都能看到的,总结了一些我认为比较重要的要点。下面是我自己在使用service的时候的一点心得,以后体会到更多再加。
1 service与Activity的通信
service一般都是一个后台线程,处理如下载、文件存取等费时操作。而这些操作完成以后一般都需要通知ui,这就需要在activity中与后台service通信。
通信的方式是在activity中调用
方法,注意service中需要重写onBind(),不然无法bind成功。ServiceConnection是一个回调对象,需要实现两个方法:
public void onServiceConnected(ComponentName className, IBinder service) {}
public void onServiceDisconnected(ComponentName arg0) {}
我们应该在onServiceConnected方法中,获取到bind到的service对象:
DownloadBinder binder = (DownloadBinder) service;
mService = binder.getService();
并且调用service中的public方法向service中注册Handler,这里的Handler在activity中定义。
service执行完onHandlerIntent (intentServict)或者自己新建的线程(普通service)执行结束,并且需要通知activity时,就可以直接通过注册进来的Handler发送消息,并更新ui。
不同的activity都可以相同一个service注册Handler,但是注意handler是隶属于一个线程的(这个说法好像不是太合理,求更正),所有的activity都在同一个主线程中运行,所以,实际上,只会同时有一个activity的handler会被注册到service中。
注意:
1 如果我们需要在service中做一些不费时并且需要马上返回结果的事情,例如:下载开始时,先判断是否满足下载条件,满足条件就提示下载开始并另启线程进行下载,否则提示用户不能下载,这时候,应该在onStartCommand 方法中进行判断处理,并立刻提示用户,如果满足条件,就启动新线程或者调用super.onStartCommand(intentService情况)。
2 activity一定要记得unbindService(mConnection);否则会造成connection leaked异常,不会提示程序错误,但是会影响软件稳定性。我一般都是在onResume中bindService,在onPause中unbindService(mConnection);