Android四大组件之Service

1、什么是service

一个可以在后台执行长时间操作而不需要用户界面的应用组件。

需要注意的是:

- 服务并不是运行在一个独立的进程中,而是依赖于创建服务时所在的应用程序进程。也就是运行在主线程中。

- 服务并不会自动开启线程,所有的代码都默认运行在主线程中。也就是说我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就可能出现主线程被阻塞的情况。

2、如何创建service

- 定义一个类继承Sevice,或者其子类IntentService(区别在后面讲到),重写里面一写关键的回调方法。

- 并在清单文件中申明,并根据需要配置一些其他属性。

~~~

android:enabled=["true" | "false"]

android:exported=["true" | "false"]

android:icon="drawable resource"

android:isolatedProcess=["true" | "false"]

android:label="string resource"

android:name="string"

android:permission="string"

android:process="string" >

~~~

android:enabled : 如果为true,则这个service可以被系统实例化,如果为false,则不行。默认为true

android:exported : 如果为true,则其他应用的组件也可以调用这个service并且可以与它进行互动,如果为false,则只有与service同一个应用或者相同user ID的应用可以开启或绑定此service。它的默认值取决于service是否有intent filters。如果一个filter都没有,就意味着只有指定了service的准确的类名才能调用,也就是说这个service只能应用内部使用——其他的应用不知道它的类名。这种情况下exported的默认值就为false。反之,只要有了一个filter,就意味着service是考虑到外界使用的情况的,这时exported的默认值就为true

android:icon : 一个象征着这个service的icon

android:isolatedProcess : 如果设置为true,这个service将运行在一个从系统中其他部分分离出来的特殊进程中,我们只能通过Service API来与它进行交流。默认为false。

android:label : 显示给用户的这个service的名字。如果不设置,将会默认使用的label属性。

android:name : 这个service的路径名,例如“com.lypeer.demo.MyService”。这个属性是唯一一个必须填的属性。

android:permission : 其他组件必须具有所填的权限才能启动这个service。

android:process : service运行的进程的name。默认启动的service是运行在主进程中的。

3、如何启动service

startService()方式

组件如activity通过调用startStartService()方法,就可以启动一个特定的service,在方法中传递一个intent参数,通关intent参数获取数据。一旦启动后,service就会独立运行在后台,即使调用的组件以及销毁,service还可以继续在后台运行。当操作完成后service自行调用stopService()或者有组件调用针对它的stopService()来结束运行。应用被强制清理,service也会被杀死。

bindService()方式

比startService()方式复杂,同时使用这种方式启动的service也能完成更多的事情,比如其他组件可向其发送请求,接受来自它的响应,甚至通过它来进行IPC等等。我们通常将绑定它的组件成为客户端,而称它为服务器。

如果要创建一个支持绑定的service,我们必须要重写它的onBind()方法。这个方法会返回一个IBinder对象,它是客户端用来和服务器进行交互的接口。而要得到IBinder接口,我们通常有三种方式:继承Binder类,使用Messenger类,使用AIDL。

并且多个组件可以同时对一个 Service 进行绑定,只有在所有进行了绑定的组件都解绑的时候,Service 才会销毁。

service和  IntentService

如果是扩建Service类的话,通常情况下我们需要新建一个用于执行工作的新线程,因为默认情况下service将工作于应用的主线程,而这将会降低所有正在运行的Activity的性能。而IntentService就不同了。它是Service的子类,它使用工作线程来处理所有的startService请求。如果你不要求这个service要同时处理多个请求,那么继承这个类显然要比直接继承Service好

IntentService已经做了这些事:

- 创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent

- 创建工作队列,用于将一个 Intent 逐一传递给 onHandleIntent() 实现,这样的话就永远不必担心多线程问题了

- 在处理完所有启动请求后停止服务,从此妈妈再也不用担心我忘记调用 stopSelf() 了

- 提供 onBind() 的默认实现(返回 null)

- 提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent() 实现

因此我们只需要实现onHandleIntent()方法来完成具体的功能逻辑就可以了。

要注意的是,如果需要重写其他的方法,比如onDestroy()方法,一定不要删掉它的超类实现!因为它的超类实现里面也许包括了对工作线程还有工作队列的初始化以及销毁等操作,如果没有了的话很容易出问题。

如果你有让service同时处理多个请求的需求,这个时候就只能去继承Service了。这个时候就要自己去处理工作线程那些事。下面是一个官方的栗子:

~~~

public class HelloService extends Service {

private Looper mServiceLooper;

private ServiceHandler mServiceHandler;

private final class ServiceHandler extends Handler {

public ServiceHandler(Looper looper) {

super(looper);

}

@Override

public void handleMessage(Message msg) {

long endTime = System.currentTimeMillis() + 5*1000;

while (System.currentTimeMillis() < endTime) {

synchronized (this) {

try {

wait(endTime - System.currentTimeMillis());

} catch (Exception e) {

}

}

}

stopSelf(msg.arg1);

}

}

@Override

public void onCreate() {

HandlerThread thread = new HandlerThread("ServiceStartArguments",

Process.THREAD_PRIORITY_BACKGROUND);

thread.start();

mServiceLooper = thread.getLooper();

mServiceHandler = new ServiceHandler(mServiceLooper);

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();

Message msg = mServiceHandler.obtainMessage();

msg.arg1 = startId;

mServiceHandler.sendMessage(msg);

return START_STICKY;

}

@Override

public IBinder onBind(Intent intent) {

return null;

}

@Override

public void onDestroy() {

Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();

}

}

~~~

比起IntentService来,显然做的工作要多的多的多。但是,由于是自己处理的对onStartCommand的调用,它可以同时执行多个请求——虽然官方的栗子里没有这样做。但是如果你想这样做,就可以为每一个请求创建一个线程,然后立即运行这些请求。

- START_NOT_STICKY : 如果系统在 onStartCommand() 返回后终止服务,则除非有挂起 Intent 要传递,否则系统不会重建服务。这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务。

- START_STICKY : 如果系统在 onStartCommand() 返回后终止服务,则会重建服务并调用 onStartCommand(),但绝对不会重新传递最后一个 Intent。相反,除非有挂起 Intent 要启动服务(在这种情况下,将传递这些 Intent ),否则系统会通过空 Intent 调用 onStartCommand()。这适用于不执行命令、但无限期运行并等待作业的媒体播放器(或类似服务)。

- START_REDELIVER_INTENT : 如果系统在 onStartCommand() 返回后终止服务,则会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand()。任何挂起 Intent 均依次传递。这适用于主动执行应该立即恢复的作业(例如下载文件)的服务。


原文:http://www.jianshu.com/p/d46f20695cb7

原文:http://blog.csdn.net/luoyanglizi/article/details/51980630

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 服务基本上分为两种形式 启动 当应用组件(如 Activity)通过调用 startService() 启动服务时...
    pifoo阅读 1,202评论 0 8
  • Service的相关知识虽然简单,但是也比较琐碎,其衍生知识也比较多。本篇从Service的生命周期、运行和使用方...
    卑鄙的鹿尤菌阅读 781评论 0 1
  • Service的生命周期 service的生命周期,从它被创建开始,到它被销毁为止,可以有两条不同的路径: A s...
    _执_念__阅读 1,518评论 0 19
  • 是什么让我总是,意外地看到你神情暗淡独自站在那里,是什么让我总是心痛地看着你忧郁的背影,有种想去抱你的冲动.每次看...
    徜徉未来阅读 250评论 1 1
  • 有了一个回复。 评记的是那年张北草原音乐节布衣乐队《秋天》的事。 回复我的还是个网易认证的歌手。 他也曾跟我一样在...
    郭永伟阅读 348评论 0 0