Service

第一大要点::千万不要忘了注册,不注册,启动个屁啊

一、Service服务介绍

Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

警告:service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。

二、Service两种启动方式

Service有两种状态,“启动的”和“绑定”

1.两种启动方式的特点:

通过startService()启动的服务处于“启动的”状态,一旦启动,service就在后台运行,即使启动它的应用组件已经被销毁了。通常started状态的service执行单任务并且不返回任何结果给启动者。比如当下载或上传一个文件,当这项操作完成时,service应该停止它本身。

还有一种“绑定”状态的service,通过调用bindService()来启动,一个绑定的service提供一个允许组件与service交互的接口,可以发送请求、获取返回结果,还可以通过夸进程通信来交互(IPC)。绑定的service只有当应用组件绑定后才能运行,多个组件可以绑定一个service,当调用unbind()方法时,这个service就会被销毁了。

2.Service生命周期中的一些方法:
        


通过这个图可以看到,两种启动service的方式以及他们的生命周期,bind service的不同之处在于当绑定的组件销毁后,对应的service也就被kill了。service的声明周期相比与activity的简单了许多,只要好好理解两种启动service方式的异同就行。

service生命周期也涉及一些回调方法,这些方法都不用调用父类方法,具体如下:

public class ExampleService extends Service {  
    int mStartMode;       // indicates how to behave if the service is killed  
    IBinder mBinder;      // interface for clients that bind  
    boolean mAllowRebind; // indicates whether onRebind should be used  

    @Override  
    public void onCreate() {  
        // The service is being created  
    }  
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        // The service is starting, due to a call to startService()  
        return mStartMode;  
    }  
    @Override  
    public IBinder onBind(Intent intent) {  
        // A client is binding to the service with bindService()  
        return mBinder;  
    }  
    @Override  
    public boolean onUnbind(Intent intent) {  
        // All clients have unbound with unbindService()  
        return mAllowRebind;  
    }  
    @Override  
    public void onRebind(Intent intent) {  
        // A client is binding to the service with bindService(),  
        // after onUnbind() has already been called  
    }  
    @Override  
    public void onDestroy() {  
        // The service is no longer used and is being destroyed  
    }  
}

三、服务(Service)的停止和启动

1 .如果service是非绑定的,最终当任务完成时,为了节省系统资源,一定要停止service,可以通过stopSelf()来停止,也可以在其他组件中通过stopService()来停止。
绑定的service可以通过onUnBind()来停止service。

2. 有了 Service 类我们如何启动他呢,有两种方法:

     •Context.startService()      •Context.bindService()

    1. 在同一个应用任何地方调用startService() 方法就能启动Service 了,然后系统会回调Service 类的 onCreate() 以及 onStartCommand() 方法。这样启动的Service 会一直运行在后台,直到Context.stopService() 或者 StopSelf() 方法被调用。另外如果一个Service 已经被启动,其他代码再试图调用startService() 方法,是不会执行onCreate() 的,但会重新执行一次onStartCommand() 。

    2. 另外一种 bindService() 方法的意思是,把这个Service 和调用 Service 的客户类绑起来,如果调用这个客户类被销毁,Service 也会被销毁。用这个方法的一个好处是,bindService() 方法执行后 Service 会回调上边提到的 onBind() 方法你可以从这里返回一个实现了 IBind 接口的类,在客户端操作这个类就能和这个服务通信了,比如得到 Service 运行的状态或其他操作。如果 Service 还没有运行,使用这个方法启动 Service 就会 onCreate() 方法而不会调用 的onStartCommand()。

   3.总结:
      1. startService()的目的是回调的onStartCommand方法,onCreate() 方法是在Service不存在的时候调用的,如果Service存在(例如之前调用了bindService,那么Service的onCreate方法已经调用了)那么startService()将跳过onCreate() 方法。

     2. bindService()目的是回调onBind()方法,它的作用是在Service和调用者之间建立一个桥梁,并不负责更多的工作(例如一个Service需要连接服务器的操作),一般使用bindService来绑定到一个现有的Service(即通过StartService启动的服务)。

      由于Service 的onStartCommand()方法只有在startService()启动Service的情况下才调用,故使用的onStartCommand()的时候要注意这点。

4.  与 Service 通信并且让它持续运行
     如果我们想保持和Service 的通信,又不想让Service 随着 Activity 退出而退出呢?你可以先startService() 然后再 bindService() 。当你不需要绑定的时候就执行unbindService() 方法,执行这个方法只会触发Service 的 onUnbind() 而不会把这个 Service 销毁。这样就可以既保持和 Service 的通信,也不会随着 Activity 销毁而销毁了。

四、IntentService

另外,这里要说明Service的一个子类,IntentService,首先看下官方文档的说明:
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。而在一般的继承Service里面如果要进行耗时操作就必须另开线程,但是使用IntentService就可以直接在里面进行耗时操作,因为默认实现了一个worker thread。对于异步的startService请求,IntentService会处理完成一个之后再处理第二个。

看下IntentService的具体实现:

public class HelloIntentService extends IntentService {  

  /**  
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */  
  public HelloIntentService() {  
     super("HelloIntentService");  
  }  

  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */  
  @Override  
  protected void onHandleIntent(Intent intent) {  
      // Normally we would do some work here, like download a file.  
      // For our sample, we just sleep for 5 seconds.  
      long endTime = System.currentTimeMillis() + 5*1000;  
      while (System.currentTimeMillis() < endTime) {  
         synchronized (this) {  
             try {  
                 wait(endTime - System.currentTimeMillis());  
             } catch (Exception e) {  
             }  
         }  
      }  
  }  
}



### Service的生命周期和状态 Service在Android系统中可以分为两种主要状态:启动状态和绑定状态。当一个Service被启动后,它会在后台长时间运行,即使启动它的组件已经被销毁,Service仍然可以继续运行[^2]。如果一个Service既被启动又被绑定,那么它会同时处于这两种状态。 ### Service的生命周期方法 自定义的Service需要继承`Service`基类,并且通常需要重写一些生命周期方法来实现特定的功能: - `onCreate()`:当Service第一次创建时调用。如果Service已经存在,则不会调用此方法。 - `onStartCommand(Intent intent, int flags, int startId)`:当其他组件通过调用`startService()`方法请求启动Service时调用。在这个方法里可以处理长时间运行的操作。 - `onBind(Intent intent)`:当其他组件通过调用`bindService()`方法绑定到Service时调用。该方法返回一个`IBinder`接口,允许客户端与Service进行通信。 - `onUnbind(Intent intent)`:当所有绑定到Service的客户端都解绑后调用。 - `onDestroy()`:当Service不再使用并被销毁时调用。这是释放资源的好时机。 ### 启动状态下的Service一个Service通过调用`startService()`方法启动时,它进入启动状态。在这种状态下,Service独立于启动它的组件运行,直到它自己停止或被系统终止。要停止这样的Service,可以在Service内部调用`stopSelf()`方法,或者从外部组件调用`stopService()`方法[^1]。 ### 绑定状态下的Service 当组件通过调用`bindService()`方法绑定Service时,Service进入绑定状态。此时,组件可以通过`ServiceConnection`对象获取到Service提供的`IBinder`对象,从而与Service进行交互。绑定状态下的Service可以被多个组件绑定,只有当所有绑定的组件都解绑后,Service才会被销毁[^3]。 ### Service的声明 无论哪种类型的Service,都需要在`AndroidManifest.xml`文件中声明。声明格式如下: ```xml <service android:name=".Demo2Service" /> ``` 其中`.Demo2Service`是你的Service类名[^2]。 ### Service的绑定过程 为了与Service进行交互,组件需要创建一个`ServiceConnection`实例,并实现其`onServiceConnected()`和`onServiceDisconnected()`回调方法。例如: ```java private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 这里 IBinder类型的service 就是我们要绑定的那个service // 通过这个service,Activity就可以调用MyBindService.MyBinder中的方法 } @Override public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "onServiceDisconnected: "); } }; ``` 然后,组件可以通过调用`bindService()`方法来绑定Service,并在不需要时调用`unbindService()`方法来解绑[^5]。 ### Service的应用场景 Service非常适合用来执行那些不需要用户界面但需要长时间运行的任务。比如播放音乐、下载文件、处理网络请求等。此外,Service还可以与其他组件进行交互,包括跨进程通信(IPC)[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值