关于Service

来源:互联网 发布:oracle sql列转行函数 编辑:程序博客网 时间:2024/05/16 15:18
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 (callingonCreate() 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类。它本身会启动一个后台线程

0 0