android之Service总结

简介 


   Service 是Android四大组件之一。与Activity比较相似,它们都代表可执行的程序。Service与Activity的区别在于:Service一直在后台运行,它没有用户界面,具有自己的生命周期。在开发中,如果某个程序组件需要在运行时向用户呈现某种界面,或者该程序需要与用户交互,就需要使用Activity,否则就应该考虑Service。

Service分类


 按照启动方式的不同Service可以分为两类:

        1>Started Service :在后台,作为一个独立的可执行单元不能与调用者进行交互,适合在后台做一些独立的耗时任务,比如:下载、上传。

        2>Bound Service :类似client-server模式,此类Service可被多个client端绑定,client与Service可实现双向通信。

下面就按照此分类介绍其创建、启动、销毁、生命周期等一系列知识

1>Started Service

 A.创建Service步骤: 

  类似Activity的开发步骤:1.开发一个Activity子类 2.在配置文件中配置Activity,开发Service也需要两个步骤。

     1》定义一个派生自Service或ServiceIntent的子类。

    2》在AndroidManifest.xml中配置之

配置示例代码: 

<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

Note:Service 的配置与Activity基本相同,如果开发的Service只供本应用调用则不需要为其配置intent-filter 标签。Service标签下可以配置许多属性,了解更多请参考这里

  示例1:继承自Service

View Code
 1 package com.example.services;
 2 
 3 import android.app.Service;
 4 import android.content.Intent;
 5 import android.os.IBinder;
 6 
 7 public class Myservice extends Service {
 8 
 9     @Override
10     public IBinder onBind(Intent intent) {
11         System.out.println("onBind");
12         return null;
13     }
14 
15     @Override
16     public void onCreate() {
17         System.out.println("onCreate");
18         super.onCreate();
19     }
20 
21     @Override
22     public int onStartCommand(Intent intent, int flags, int startId) {
23         System.out.println("onStartCommand");
24         return super.onStartCommand(intent, flags, startId);
25 
26     }
27 
28     @Override
29     public void onDestroy() {
30         System.out.println("onDestroy");
31         super.onDestroy();
32     }
33 }

  示例2:继承自ServiceIntent

View Code
 1 package com.example.services;
 2 
 3 import android.content.Intent;
 4 
 5 public class ExtendIntentService extends android.app.IntentService {
 6 
 7     public ExtendIntentService() {
 8         super("ExtendIntentService");
 9     }
10 
11     @Override
12     protected void onHandleIntent(Intent intent) {
13         System.out
14                 .println("onHandleIntent:" + Thread.currentThread().getName());
15     }
16 
17     @Override
18     public void onCreate() {
19         super.onCreate();
20         System.out.println("onCreate:" + Thread.currentThread().getName());
21     }
22 
23     @Override
24     public int onStartCommand(Intent intent, int flags, int startId) {
25         System.out
26                 .println("onStartCommand:" + Thread.currentThread().getName());
27         return super.onStartCommand(intent, flags, startId);
28     }
29 
30     @Override
31     public void onDestroy() {
32         super.onDestroy();
33         System.out.println("onDestroy");
34     }
35 
36 }

分析:

  示例1

    继承自Service类,需要我们根据需要实现特定的几个回调方法主要有以下几个:

      onBind(Intent intent):该方法是子类必须要实现的方法。该方法返回一个IBinder对象,应用程序可通过此对象与Service通信。

      onCreate():当Service第一次被创建时将回调此方法。

      onDestroy():当该Service被销毁时将回调此方法。

      onStart(Intent intent, int startId):已被标注Deprecated,被onStartCommand方法取代,其实onStartCommand在内部也是调用onStart,只是多了个int返回值。

      int onStartCommand(Intent intent, int flags, int startId):该方法的早期版本是onStart(Intent intent, int startId),每当客户端调用startService(Intent)时系统将        回调此方法。其有一个int返回值,系统根据此值决定当系统由于某种原因(比如:内存紧张)销毁此service后,是否重启它及对intent的处理细节。

      onUnbind(Intent intent):当service上绑定的所有方法都断开链接时,将回调此方法。

通过这种方式,我们操作的灵活性较高,但请注意对于某些耗时性的操作我们应该为其开一个单独的线程,以防阻塞UI主线程,因为Service也是运行在主线程中的,对于某些实时性要求较高的请求,我们也可以为其开单独的线程处理。

  示例2

    继承自ServiceIntent,其中我们只需实现onHandleIntent(Intent intent)方法。ServiceIntent也是Service的一个子类,里面默认实现好了一套消息处理机制(一个单独的线程,Handler,Looper),在onHandleIntent中是按照FIFO的方式处理所有Client发送过来的intent请求。

B.启动Service

  这里只讲通过startService(intent)方式,另一种方式将在下面介绍。我们一般会在Activity中开启一个Service,示例代码:

 1 final Intent intent_Service = new Intent(this,
 2                 ExtendIntentService.class);
 3 
 4         findViewById(R.id.start).setOnClickListener(new OnClickListener() {
 5 
 6             @Override
 7             public void onClick(View v) {
 8                 System.out.println("startService");
 9                 startService(intent);
10             }
11         });
View Code

C.关闭Service

  通过start方式启动service,此service并不会自己销毁,即使启动它的组件(比如:Activity)已销毁。所以当我们通过这种方式启动service后一定要记得在合适的时机主动关闭它。我们可以通过stopService(intent)方法在某个组件中关闭,也可以通过stopSelf()方法,在service中关闭。stopService方法还有另一种形式:void stopSelf(int startId),startId用于区分不同的intent的请求。此方法的作用是:我们可以在Service中每处理完一个请求,就调用一次stopSelf(int startId)方法,但此方法并不会真正关闭service,只有当service中所有的请求都处理完后才会关闭service.此方法可防止出现任务未处理完就关闭Service的情况。

D.生命周期

  图1

说明:上面我们所讲的对应此图的左半幅,即通过start方式。

2>Bound Service

A.创建步骤

    1>写一个继承自Service的子类

    2>在1>中定义的Service中实现一个IBinder类型的接口,以供onBind方法返回到client端,client与service也是通过此接口实现通信的

 IBinder类型的接口,有三种实现方式:

  1>继承Binder类:如果你开发的Service只供当前应用使用,采用这种方式是最佳的。在此Binder类中要实现一些公共的方法以供client端调用,或者返回当前service实例。

示例:

 1 public class LocalService extends Service {
 2     // Binder given to clients
 3     private final IBinder mBinder = new LocalBinder();
 4     // Random number generator
 5     private final Random mGenerator = new Random();
 6 
 7     /**
 8      * Class used for the client Binder.  Because we know this service always
 9      * runs in the same process as its clients, we don't need to deal with IPC.
10      */
11     public class LocalBinder extends Binder {
12         LocalService getService() {
13             // Return this instance of LocalService so clients can call public methods
14             return LocalService.this;
15         }
16     }
17 
18     @Override
19     public IBinder onBind(Intent intent) {
20         return mBinder;
21     }
22 
23     /** method for clients */
24     public int getRandomNumber() {
25       return mGenerator.nextInt(100);
26     }
27 }
View Code  
 1 public class BindingActivity extends Activity {
 2     LocalService mService;
 3     boolean mBound = false;
 4 
 5     @Override
 6     protected void onCreate(Bundle savedInstanceState) {
 7         super.onCreate(savedInstanceState);
 8         setContentView(R.layout.main);
 9     }
10 
11     @Override
12     protected void onStart() {
13         super.onStart();
14         // Bind to LocalService
15         Intent intent = new Intent(this, LocalService.class);
16         bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
17     }
18 
19     @Override
20     protected void onStop() {
21         super.onStop();
22         // Unbind from the service
23         if (mBound) {
24             unbindService(mConnection);
25             mBound = false;
26         }
27     }
28 
29     /** Called when a button is clicked (the button in the layout file attaches to
30       * this method with the android:onClick attribute) */
31     public void onButtonClick(View v) {
32         if (mBound) {
33             // Call a method from the LocalService.
34             // However, if this call were something that might hang, then this request should
35             // occur in a separate thread to avoid slowing down the activity performance.
36             int num = mService.getRandomNumber();
37             Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
38         }
39     }
40 
41     /** Defines callbacks for service binding, passed to bindService() */
42     private ServiceConnection mConnection = new ServiceConnection() {
43 
44         @Override
45         public void onServiceConnected(ComponentName className,
46                 IBinder service) {
47             // We've bound to LocalService, cast the IBinder and get LocalService instance
48             LocalBinder binder = (LocalBinder) service;
49             mService = binder.getService();
50             mBound = true;
51         }
52 
53         @Override
54         public void onServiceDisconnected(ComponentName arg0) {
55             mBound = false;
56         }
57     };
58 }
View Code  

  2>利用Messenger:如果你的service要提供被别的应用访问的功能(进程间访问)就要利用此方式

示例:

 1 public class MessengerService extends Service {
 2     /** Command to the service to display a message */
 3     static final int MSG_SAY_HELLO = 1;
 4 
 5     /**
 6      * Handler of incoming messages from clients.
 7      */
 8     class IncomingHandler extends Handler {
 9         @Override
10         public void handleMessage(Message msg) {
11             switch (msg.what) {
12                 case MSG_SAY_HELLO:
13                     Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
14                     break;
15                 default:
16                     super.handleMessage(msg);
17             }
18         }
19     }
20 
21     /**
22      * Target we publish for clients to send messages to IncomingHandler.
23      */
24     final Messenger mMessenger = new Messenger(new IncomingHandler());
25 
26     /**
27      * When binding to the service, we return an interface to our messenger
28      * for sending messages to the service.
29      */
30     @Override
31     public IBinder onBind(Intent intent) {
32         Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
33         return mMessenger.getBinder();
34     }
35 }
View Code
 1 public class ActivityMessenger extends Activity {
 2     /** Messenger for communicating with the service. */
 3     Messenger mService = null;
 4 
 5     /** Flag indicating whether we have called bind on the service. */
 6     boolean mBound;
 7 
 8     /**
 9      * Class for interacting with the main interface of the service.
10      */
11     private ServiceConnection mConnection = new ServiceConnection() {
12         public void onServiceConnected(ComponentName className, IBinder service) {
13             // This is called when the connection with the service has been
14             // established, giving us the object we can use to
15             // interact with the service.  We are communicating with the
16             // service using a Messenger, so here we get a client-side
17             // representation of that from the raw IBinder object.
18             mService = new Messenger(service);
19             mBound = true;
20         }
21 
22         public void onServiceDisconnected(ComponentName className) {
23             // This is called when the connection with the service has been
24             // unexpectedly disconnected -- that is, its process crashed.
25             mService = null;
26             mBound = false;
27         }
28     };
29 
30     public void sayHello(View v) {
31         if (!mBound) return;
32         // Create and send a message to the service, using a supported 'what' value
33         Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
34         try {
35             mService.send(msg);
36         } catch (RemoteException e) {
37             e.printStackTrace();
38         }
39     }
40 
41     @Override
42     protected void onCreate(Bundle savedInstanceState) {
43         super.onCreate(savedInstanceState);
44         setContentView(R.layout.main);
45     }
46 
47     @Override
48     protected void onStart() {
49         super.onStart();
50         // Bind to the service
51         bindService(new Intent(this, MessengerService.class), mConnection,
52             Context.BIND_AUTO_CREATE);
53     }
54 
55     @Override
56     protected void onStop() {
57         super.onStop();
58         // Unbind from the service
59         if (mBound) {
60             unbindService(mConnection);
61             mBound = false;
62         }
63     }
64 }
View Code    

  3>利用AIDL

    待续...

B.绑定到Service

  通过bindService (Intent service, ServiceConnection conn, int flags)方法。第一个参数就是一个普通的Intent包含了所要绑定的Service名。第二个参数ServiceConnection需要我们自己在Client端定义。里面有两个方法要我们实现。一个是onServiceConnected(ComponentName name, IBinder service),此方法会在绑定成功时被回调,其中的第二个参数service就是那个我们在Service中定义的接口,通过它我们可以访问Service,以实现某些功能。void onServiceDisconnected (ComponentName name),当client与service断开连接时将回调此方法。

C.生命周期

   

  

总结:

   1>service可以分为两种:1.started service; 2.Bound service。

   2>started service:与启动方无关联,被启动后在后台作为一个独立的执行单元运行,此类service一定要记得关闭,否则会一直在后台运行。有两种关闭方式a.在某个组件类中调用stopService方法 b.在service内部合适的地方与时机(任务完成时)调用stopSelf方法。此类service适合在后台做一些较独立的任务,比如:下载、上传...

     3>Bound service:此类service类似client-server模式中的server端,一个server可以被不同的组件绑定。绑定成功后,可以调用service内容提供的公共方法。此类service还可以提供进程间的通信。当所有的客户端都与其断开连接后,系统将回调其onDestroy方法,因此针对此类型的service不需要我们显式去关闭。

     4>一个通过startService方法启动后的service,还可以被别的组件通过bindService方法绑定。

     5>service作为android的四大组件之一,它也是运行在主线程中的。因此,如果要在service中作耗时性的操作最好要开新的线程。

     6>由于系统资源紧张问题,导致service被系统杀死,在以后某个时刻资源不再紧张,则系统会自动重启它。具体规则可以看onStartCommand方法的返回值 。  7>对于bound型service,若开启它的组件(比如activity)销毁后,此service也会被销毁,不管是否在那个activity的onDestory中调用unBindService方法。

ps:有点懒了,示例代码直接copy的官方文档中的。还有很多细节并没有介绍到。官方文档中介绍的真是太全了,英语还行的朋友,建议直接看文档。

原文地址:https://www.cnblogs.com/byghui/p/3076398.html