阅读时有疑惑的地方:
- 继承IntentService类,它本身提供了一个工作者进程,可以接收onStartCommond发送过来的请求,关键是这句话“Stops the service after all start requests have been handled, so you never have to call stopSelf()”,意思是它在所有请求都被处理以后,也就是被onHandleIntent()处理以后,自己就会关闭。是不是说,发送了一个请求,处理了以后,它就关闭了?还是说,非得同时发送了多个请求,或者在onHandlerIntent的处理过程中也持续不断的有请求过来,当这段处理都过去以后,它就自己关掉了?那这样不是一次性的服务吗?万一想隔十分钟调用一次Service,而处理只是一瞬间,那是不可以理解成每次调用,都是重新启动的它。
- 停止服务,stopService和stopSelf方法,为了保证当前关闭时,没有新的请求过来导致误关,SDK建议用stopSelf方法来关闭,该方法有一个id的参数,id是onStartCommon的请求ID,这样能够保证关掉的是最后。但是这个id要怎么和stopSelf方法结合起来用呢?是说每次在onStartCommond调用的时候,把最新这一次的startId先放在全局变量里面,然后在其他地方,比如onStartCommond处理完了以后,再调用stopSelf(startId)方法来结束Service。它这时候是不是把这个startId和Service本身生成的最新startId比较,若相同,就可以结束掉Service,否则,就不结束。也就是说,只要有一次请求,不管有没有在Service里面执行,都会相应的生成一个startId。这样就能保证在request没有全部被处理时,无法结束Service.
- 要单独处理的话,为啥不直接用线程,而要用Service?
主要包括以下三个方面:
- service概况
- 如何创建service
- 生命周期
一、Service概况
Service是一个可以执行后台操作的应用程序组件,主要是用来执行一些后台的耗时操作,常见比如请求网络、播放音乐、读取文件、读取数据库等。它没有自己的线程,是运行在主线程里面的,也即和UI的那个线程是一样的,因而,在Service里面,一定要记得新起一个线程来做自己想要做的操作。Service主要分成两类:
- Service 常规的Service
- bindService 绑定方式创建的Service
区别主要是调用方式不一样,常规的通过startService方法来调用,触发onStartCommond()方法,需要在Service中控制它的结束或者在客户端调用结束的方法来结束;而bindService通过bindService方法来调用,触发onBind()方法,当所有bind的client都unBlind后,会由系统来自动结束掉。
运行在后台的Service可以被系统给杀掉,而标记为foreground的Service则不可以。在AndroidManifest.xml中的Service节点,定义时,也可以把Service定义成是否允许其它应用程序访问(android:exported属性),以及定义自己的intent filter接受请求。
二、创建Service
创建常规的Service主要有两种方式:
- 继承Service类。需要自己负责处理从onStartCommond()方法接收到的多个请求,可以针对每个请求单独开一个线程来并行处理;
package com.example.android.apistudy.service; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; import android.support.v4.app.NotificationCompat; import com.example.android.apistudy.project.R; import com.example.android.apistudy.project.ShowInfoActivity; public class BackGroundService extends Service { private ServiceHandler mHandler; @Override public void onCreate(){ HandlerThread thread=new HandlerThread("mythread",Process.THREAD_PRIORITY_BACKGROUND); thread.start(); Looper looper=thread.getLooper(); mHandler=new ServiceHandler(looper); } @Override public int onStartCommand(Intent intent,int flags,int startId){ Message msg=new Message(); mHandler.sendMessage(msg); return START_STICKY; } @Override public IBinder onBind(Intent arg0) { // TODO Auto-generated method stub return null; } @Override public void onDestroy(){ Message msg=new Message(); mHandler.sendMessage(msg); } private final class ServiceHandler extends Handler{ public ServiceHandler(Looper looper){ super(looper); } @Override public void handleMessage(Message msg){ NotificationCompat.Builder mBuilder=new NotificationCompat.Builder(getApplicationContext()); mBuilder.setSmallIcon(R.drawable.ic_launcher); mBuilder.setContentTitle("Title::::"); mBuilder.setContentText("content......"); PendingIntent pendingIntent=PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(),ShowInfoActivity.class), 0); mBuilder.setContentIntent(pendingIntent); NotificationManager manager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(0, mBuilder.build()); } } }
- 继承IntentService类。实现了一个工作者线程,用来管理所有发送过来的请求,并且触发onHandleIntent()方法来处理,但是不适用于请求同时并发的情况,适合一次性的请求操作。
package com.example.android.apistudy.service; import android.app.IntentService; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Process; import android.support.v4.app.NotificationCompat; import com.example.android.apistudy.project.R; import com.example.android.apistudy.project.ShowInfoActivity; public class BackGroundIntentService extends IntentService { public BackGroundIntentService() { super("backgroundIntentService"); // TODO Auto-generated constructor stub } @Override protected void onHandleIntent(Intent intent) { NotificationCompat.Builder mBuilder=new NotificationCompat.Builder(getApplicationContext()); mBuilder.setSmallIcon(R.drawable.ic_launcher); mBuilder.setContentTitle("Title::::"); mBuilder.setContentText("content......"); PendingIntent pendingIntent=PendingIntent.getActivity(getApplicationContext(), 0, new Intent(getApplicationContext(),ShowInfoActivity.class), 0); mBuilder.setContentIntent(pendingIntent); NotificationManager manager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(0, mBuilder.build()); } }
这个通知不会在点了一下以后消失,只有当Service停止以后才会消失。
三、生命周期
借用下SDK里面的生命周期图:
两种创建Service的方式,对应于不同的生命周期。木有onStop回调函数,Service销毁以后,都是触发onDestroy方法。同时,普通的Service也可以通过bind的方式来访问。是否一旦使用bind方式以后,Service就不能被人为给停止掉。
onStartCommond()方法有三个返回值:
- START_NOT_STICKY ,当service被系统给杀掉以后,不会重新创建Service,直到下一次有新的请求过来;
- START_STICKY,当Service被系统给杀掉以后,重新创建Service,但是传递进来的intent对象是空值,并不是之前传递过的;
- START_REDELIVER_INTENT,当Service被系统给杀掉以后,重新创建Service,传递进来的intent对象是之前最新一次传递的Intent,适合下载文件的时候使用。