Service简析
简介
Service作为Android的四大组件之一,它的重要性不言而喻,之前虽说看过一些介绍但是一直没有用过,最近需要用到的时候发现无从下手,便阅读了官方的有关Service的Guide,这里总结一下。
Service作用
官方介绍如下
A Service is an application component representing either an application’s desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.
Service主要用于在后台执行长期任务或者耗时操作,在需要的时候甚至可以在应用退出的时候保持运行状态。
Service与Thread
虽说Service可以在后台执行任务,但是实际上一个Service是运行在主线程的,如果有耗时操作我们必须在Service中自己开启一个Thread避免ANR。那就会有这么一个问题,我们为什么不用Thread呢?主要的原因就是Thread的可控性不好,假设我们在一个Activity中启动了一个Thread,一旦这个Activity结束了,那么其他的Activity就没有办法拿到这个Thread的引用,更别谈控制了。可是Service不一样,一个Service整个程序只会创建一个实例,而且任何Activity都可以控制,那么Service里的Thread就可以由所有Activity控制了。而且Service作为四大组件之一,有较高级别,在后台运行不容易被系统杀掉。
Service分类
Service分为两类
- Started Service:不和其他组件通信
Bound Service:可以和其他组件通信
无论使用哪一种Service都必须重写onBind()方法,如果使用Started Service返回null就可以了。
使用Started Service
一般需要再重写两个方法
- onCreate():启动Service的时候并不存在该Service实例,就会调用该方法。
- onStartCommand(Intent intent, int flags, int startId):每次通过startService(Intent intent)启动的时候就会掉用该方法,一般在这里开启新线程。
onStartCommand(Intent intent, int flags, int startId)方法返回int类型的值,代表Service被kill后的行为,有以下三种:
- START_NOT_STICKY:表示不重新创建
- START_STICKY:表示重新创建,调用onStartCommand传入null
- START_REDELIVER_INTENT:表示重建,调用onStartCommand传入上一个Intent
为了节省资源和电量,我们在任务结束后必须关闭Service,想要关闭Service可以通过本身调用stopSelf()或者其他组件调用stopService(),但是如果我们的Service处理多个onStartCommand请求的时候,我们在请求结束后掉用stopSelf()可能会打断已经收到的新的请求,最好的情况就是我们本身就是最后一个请求,stopSelt(int)的一个参数的重载可以解决这个方法,传入的id就是onStartCommand传递进来的id,代表当前任务的id,它会把传入的id和最后一个id比较,如果一样的话就代表本身是最后一个任务,就会stop掉,否则不会执行stop。
使用Bound Service
主要和Started Service的区别就是可以和其他组件通信,通过Binder。
创建时必须定义接口描述用户如何与Server交流,接口必须继承Binder。使用bindService()创建,必须提供一个ServiceConnection的实现,,bindService()是一个异步方法,立马回返回。当创建完后会调用ServiceConnection的onServiceConnected,并传递binder通信。onBind方法只在第一个用户连接调用,后来都返回同一个binder(因为只会有一个Service),代码如下
public class LocalService extends Service { // Binder given to clients private final IBinder mBinder = new LocalBinder(); // Random number generator private final Random mGenerator = new Random(); /** * Class used for the client Binder. Because we know this service always * runs in the same process as its clients, we don't need to deal with IPC. */ public class LocalBinder extends Binder { LocalService getService() { // Return this instance of LocalService so clients can call public methods return LocalService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } /** method for clients */ public int getRandomNumber() { return mGenerator.nextInt(100); }
bind service的代码如下
private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { // We've bound to LocalService, cast the IBinder and get LocalService instance LocalBinder binder = (LocalBinder) service; mService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName arg0) { mBound = false; } };
bindService(intent, mConnection, 0);
可以看出我们在Service中自定义了binder继承自Binder,并声明了一个方法,然后在onBind()中返回一个实例。我们会在onServiceConnected方法中得到这个binder,然后我们调用里的方法得到Service的实例,这样就可以掉用里面方法了,也就完成了通信。bindServicer第三个参数是刚开始的选择,如果是BIND_AUTO_CREATE表示如果没启动就新建
注意事项
onServiceDisconnected方法不是unbind的时候调用的,实在被kill等意外情况调用的
更多相关文章
- android应用程序最小化的处理方法
- Spring for android实现客户端与服务器的通信
- Android新线程中更新主线程UI中的View方法汇总
- 彻底解决Android 应用方法数不能超过65536的问题
- android install faild insufficient storage错误的解决方法
- Android用户界面UI组件--AdapterView及其子类(三) ExpandableLis
- [Android]ListView & ViewPager & GridView 常见问题解决方法
- Android中数据存储的几种方法
- Android退出时关闭所有Activity的方法