Android温故之-Service

Service是Android四大组件之一,常用于后台运行和组件间交互,不具备UI。Service有两种启动模式,启动模式下Service通过startService()启动,执行onCreate()→onStartCommand(),并可通过stopService()关闭;绑定模式下通过bindService()启动,执行onCreate()→onBind(),解除绑定时调用onUnbind()→onDestroy()。Service与Thread关系密切,通常在Service中创建Thread处理耗时操作。IntentService是Service子类,用于处理异步请求,通过Handler在单独线程执行任务,任务完成后自动停止。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Service概述

Service是android 系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,但不能自己运行只能后台运行,并且可以和其他组件进行交互。与Activity不同的是,Service没有自己的用户界面,因为他们不需要与用户直接交互。
Service有两种最基本的用途,一种是执行长时间运行的耗时操作(并非在Service所在的线程中处理耗时操作,而是在Service中另起一个Thread来处理耗时操作。);另一种是组件之间的交互,通过将某些功能以Service组件的形式进行封装,然后提供给其他应用组件调用,而不管这些组件是否与Service组件在同一个进程中。
Service将要不用的时候,必须手动关闭它。

Service生命周期

Service不能自己启动,必须通过其他组件来启动,根据调用的方式不同,Service的运行模式有两种,一种是启动模式,另一种则是绑定模式。因此,Service有两种不同的生命周期。

这里写图片描述

启动模式的Service的生命周期是通过Activity调用startService开始的,整个流程线:
startService() -> onCreate() -> onStartCommand() -> Service running -> context.stopService() -> onDestroy() -> Service stop

如果Service还没有运行,则android先调用onCreate(),然后调用onStartCommand();如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand方法可能会重复调用多次。如果stopService的时候会直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行,该Service的调用者再启动起来后可以通过stopService关闭Service。所以在一个生命周期中onStartCommand()可以多次调用。

绑定模式的Service的生命周期是通过组件调用绑定bindService开始的,整个流程线:
bindService() -> onCreate() -> onBind() (只一次,不可多次绑定) -> Service running -> onUnbind() -> onDestroy() -> Service stop

onBind()将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service的实例、运行状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind->onDestroy相应退出。在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。

最后,需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStartCommand()方法。它可以通过Service.stopSelf()方法或者Service.stopSelfResult()方法来停止自己,只要调用一次stopService()方法便可以停止服务,无论调用了多少次的启动服务方法。另外,这两种Service的运行模式不是完全隔离的,通过调用startService启动的Service对象实例也可以被其他进程通过bindService绑定,此时,只有对此Service实例既调用stopService也调用了unbindService后才可以彻底结束该Service。

下面新建一个Service:

public class LocationTraceService extends Service {
    private final String TAG = "LocationTraceService";
    private IMtPatrolPositionInfoMgmt gpsTraceMgmt;
    private LocationManager lm;
    private static MtPatrolPositionInfo positionInfo;// 心跳包对象
    public IMtPatrolPositionInfoMgmt getGpsTraceMgmt() {
        if (gpsTraceMgmt == null) {
            gpsTraceMgmt =    HttpClassFactory.getInstance().getServiceClass(
                    IMtPatrolPositionInfoMgmt.class);
        }
        return gpsTraceMgmt;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Log.i(TAG, " begin service create");

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }
}

Service配置申明

Service的创建需要在AndroidManifest.xml中进行申明,与Activity的申明类似。

service  
    android:name=".service.MusicService"  
    android:enabled="true" >  
    <intent-filter>  
        <action android:name="com.homer.service.musicService" />  
    </intent-filter>  
</service>  

其中, AndroidManifest.xml 里 Service 元素的常见选项
android:name (服务类名)
android:label (服务的名字,如果此项不设置,那么默认显示的服务名则为类名)
android:icon (服务的图标)
android:permission (申明此服务的权限,这意味着只有提供了该权限的应用才能控制或连接此服务)
android:process (表示该服务是否运行在另外一个进程,如果设置了此项,那么将会在包名后面加上这段字符串表示另一进程的名字)
android:enabled (如果此项设置为 true,那么 Service 将会默认被系统启动,不设置默认此项为 false)
android:exported (表示该服务是否能够被其他应用程序所控制或连接,不设置默认此项为 false)

Local Service与Remote Service

Service服务类型分为本地服务(LocalService)和远程服务(RemoteService)。

LocalService:本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。主进程被Kill后,服务便会终止。

RemoteService:远程服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。该服务是独立的进程,会占用一定资源,并且使用AIDL(Android Interface Definition Language)进行IPC(interprocess commnication)。

Service 与 Thread

首先,需要明确的是,Service 与 Thread之间没有任何的关系,其实他们也不属于同一类工具。至于为何会在此相提并论,是由于他们的作用有相似的感觉,为了防止错误地进行区分,故提出了这个对比。

Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStartCommand 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立的进程的线程上。

那么,该如何来处理Service与Thread之间的一个使用呢?一般采用的是,在一个Service中建立若干个Thread来处理Service需要耗时操作的动作,这样,便可防止主进程的main线程的阻塞,但是,却有可能造成多请求下的线程同步问题(在后面介绍的IntentService能解决该问题)。言归正传,例如,如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。

IntentService

IntentService是Service类的子类,用来处理异步请求。客户端可以通过startService(Intent)方法传递请求给IntentService。IntentService在onCreate()函数中通过HandlerThread单独开启一个线程来处理所有Intent请求对象(通过startService的方式发送过来的)所对应的任务,这样以免事务处理阻塞主线程。执行完所一个Intent请求对象所对应的工作之后,如果没有新的Intent请求达到,则自动停止Service;否则执行下一个Intent请求所对应的任务。

IntentService在处理事务时,还是采用的Handler方式,创建一个名叫ServiceHandler的内部Handler,并把它直接绑定到HandlerThread所对应的子线程。 ServiceHandler把处理一个intent所对应的事务都封装到onHandleIntent方法;因此我们直接实现onHandleIntent方法,在里面根据Intent的不同进行不同的事务处理。

public class TestService extends IntentService {

    public TestService() {
        /* 必须调用超类中以字符串为参数的构造方法,其中的
        字符串被用来作为IntentService的工作线程的名称*/
        super("TestService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        //  根据Intent的不同进行不同的事务处理

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return super.onBind(intent);
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }

}

IntentService默认实现了Onbind()方法,返回值为null
使用IntentService需要两个步骤:
1、写构造函数;
2、实现onHandleIntent方法,并在里面根据Intent的不同进行不同的事务处理就可以了。
好处:处理异步请求的时候可以减少写代码的工作量,比较轻松地实现项目的需求
注意:IntentService的构造函数一定是参数为空的构造函数,然后再在其中调用super(“name”)这种形式的构造函数。因为Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的。

参考
版权申明:本文参考内容版权归原作者所有,感谢原作者的共享。
http://blog.youkuaiyun.com/sunboy_2050/article/details/7364024
http://www.cnblogs.com/newcj/archive/2011/05/30/2061370.html
http://www.cnblogs.com/linlf03/p/3296323.html
http://blog.youkuaiyun.com/hudashi/article/details/7986130

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值