关于Service

What is a Service?

Most confusion about the Service class actually revolves around what it is  not:
  • A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
  • A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
Service不是一个进程,也不是一个线程,它运行在APP进程中的主线程中

Thus a Service itself is actually very simple, providing two main features:
  • A facility for the application to tell the system about something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to Context.startService(), which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it.
  • A facility for an application to expose some of its functionality to other applications. This corresponds to calls to Context.bindService(), which allows a long-standing connection to be made to the service in order to interact with it.
Service是APP和系统沟通的一种方式:它告诉系统它想在后台做点事情。这个跟Context.startServie()相关,用来通知系统给Service安排工作,一直工作直到别的什么东东显示的停掉它。

APP暴露自己的某些功能给别的APP的一种方式。这个跟Context.bindService()相关,它为了和Service交互而保持长期的连接

When a Service component is actually created, for either of these reasons, all that the system actually does is instantiate the component and call its  onCreate() and any other appropriate callbacks on the main thread. It is up to the Service to implement these with the appropriate behavior, such as creating a secondary thread in which it does its work.
当Service组件创建出来后,系统要做的事情就是实例化组件,在主线程调用onCreate以及别的回调。Service需要自己实现这些函数的行为---比如创建一个worker thread。

Note that because Service itself is so simple, you can make your interaction with it as simple or complicated as you want: from treating it as a local Java object that you make direct method calls on (as illustrated by  Local Service Sample), to providing a full remoteable interface using AIDL.

你可以把Service看的很简单,也可以很复杂。简单的说,Service就是一个本地的Java对象,复杂的说,还可以是一个完全的远端AIDL接口。

如何创建Service?

Service Lifecycle

There are two reasons that a service can be run by the system. If someone calls  Context.startService() then the system will retrieve the service (creating it and calling its  onCreate() method if needed) and then call its  onStartCommand(Intent, int, int) method with the arguments supplied by the client. The service will at this point continue running until  Context.stopService() or  stopSelf() is called. Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called; however, services can use their  stopSelf(int) method to ensure the service is not stopped until started intents have been processed.

系统有两种方式创建Service。某程序调用Context.startService时,系统会恢复service(调用onCreate创建它)并调用 onStartCommand方法。服务会一直运行直到Context.stopService或stopSelf被调到。另外,startService不是嵌套的,一个stopService下来,都被停止掉。

For started services, there are two additional major modes of operation they can decide to run in, depending on the value they return from onStartCommand(): START_STICKY is used for services that are explicitly started and stopped as needed, while  START_NOT_STICKY or  START_REDELIVER_INTENT are used for services that should only remain running while processing any commands sent to them. See the linked documentation for more detail on the semantics.

对于创建的service,有两个附加的主mode可以运行,基于onStartCommand的返回值:返回值是START_STRICKY用于显示的创建并停止的,START_NOT_STRICK或..用于仅保持运行来处理任何发给他们的命令的service。

Clients can also use  Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (calling onCreate() while doing so), but does not call onStartCommand(). The client will receive the  IBinder object that the service returns from its  onBind(Intent) method, allowing the client to then make calls back to the service. The service will remain running as long as the connection is established (whether or not the client retains a reference on the service's IBinder). Usually the IBinder returned is for a complex interface that has been  written in aidl.

客户端也能使用bindService来获取一个和Service的永久性连接。它同样创建了Service,但是木有调用onStartCommand。客户端将拿到IBinder(Service从onBind方法返回的),允许客户端能够有办法调用到Service。Service将保持运行直到连接不再建立---啥叫连接建立呢?就是client保留着对Service的IBinder的引用。

A service can be both started and have connections bound to it. In such a case, the system will keep the service running as long as either it is started  or there are one or more connections to it with the  Context.BIND_AUTO_CREATE flag. Once neither of these situations hold, the service's  onDestroy() method is called and the service is effectively terminated. All cleanup (stopping threads, unregistering receivers) should be complete upon returning from onDestroy().

一个服务可以既被创建又有连接附着,在这种情况下,系统将会保持服务长期运行---从被创建开始,会有一个或多个连接附着在它身上(带BIND_AUTO_CREATE标志)。
一旦任何一个情况都不存在,service的onDestroy被调用,服务被终止。所有的打扫工作(停掉线程,反注册Receiver)都需要在onDestroy中做完。

简单的说,两种调用模式:
1. 组件调用模式,onCreate onStartCommand onDestroy
2. 绑定模式,onCreate onBind onUnBind onReBind onDestroy

几个service的例子:

public  class  DLService  extends  Service{
   
     public  final  MyBinder  mBinder  =  new  MyBinder();

     @Override
     public  IBinder onBind(Intent intent) {
       
         return  mBinder  ;
    }
   
     public  class  MyBinder  extends  Binder{
       
         public  DLService getService(){
             return  DLService.  this ;
        }
       
    }
   
     public  DLCenter  mDLCenter ;
   
     @Override
     public  void  onCreate() {
         super .onCreate();
         mDLCenter  = DLCenterImp.getInstance(getApplicationContext());
    }
   
     @Override
     public  void  onDestroy() {
         super .onDestroy();
         mDLCenter .stop();
    }

     public  void  addListener(DLListener listener){
         mDLCenter .addDLListener(DLListener. TYPE_DOC , listener);
    }
   
     public  void  removeListener(DLListener listener){
         mDLCenter .removeDLListener(DLListener. TYPE_DOC , listener);
    }
   
     public  void  addDocTask(DocItem item){
         mDLCenter .addDLDocTask(item);
    }
   
     public  void  cancelDocTask(DocItem item){
         mDLCenter .removeDLDocTask(item);
    }
   
     public  void  downloadAllDoc(List<DocItem> list){
         mDLCenter .changeDLDocTaskList(list);
    }

}

context.startService的使用

MainTabActivity

startService(new Intent(getApplicationContext(), RcsService. class));

RcsService

public class RcsService extends Service {
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
     /* 此时必须执行这个函数*/
     }
}

context.bindService的使用

public abstract boolean bindService (Intent service, ServiceConnection conn,
            int flags);
public boolean bindService (Intent service, ServiceConnection conn, int flags, int userHandle) {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }
public abstract void  unbindService (ServiceConnection conn);

例子,文档下载:
在Service里
public class DLService extends Service{
    public final MyBinder mBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
         return mBinder ;//传给调用Context.bindService的人一个IBinder子类对象,该对象含一个方法,可以返回Service的对象。也就是说,通过传回来一个IBinder,传回了Service的对象。
    }
    public class MyBinder extends Binder{
        public DLService getService(){
            return DLService. this ;
        }
    }
}

所以,在Activity里,
protected void onCreate(Bundle savedInstanceState) {
     super .onCreate(savedInstanceState);
     //这里需要StartService吗?
      bindService( new Intent(this , DLService. class),  mConnection  ,
                           Context. BIND_AUTO_CREATE );
}
private DLService mDownloadService;
private ServiceConnection  mConnection = new ServiceConnection() {
               public void onServiceConnected(ComponentName className,  IBinder service) {
                       mDownloadService = ((DLService.MyBinder) service).getService();//这里拿到了Service的对象
              }

               public void onServiceDisconnected(ComponentName className) {
                       mDownloadService = null ;
              }
       };
@Override
public void onClick(View v) {
           mDownloadService .downloadAllDoc(tmplist);//这里就随便用吧,这就是远程过程调用?RPC
}
因为Service也在主线程创建和运行,因此onStartCommand函数也会阻塞主线程,因此有两种方案去避免这一点:

1. 把Service放入独立的进程,如
<service android:name="simpleService"  android:process=".a_unique_process_name">
但这样会增加一个进程

2. 在Service中另起一个线程
一个简单的策略是派生android.app.intentService类。它本身会启动一个后台线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值