zoukankan      html  css  js  c++  java
  • 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的官方文档中的。还有很多细节并没有介绍到。官方文档中介绍的真是太全了,英语还行的朋友,建议直接看文档。

  • 相关阅读:
    【左偏树+贪心】BZOJ1367-[Baltic2004]sequence
    【裸裸的左偏树】BZOJ1455-罗马游戏
    【贪心+Treap】BZOJ1691-[Usaco2007 Dec]挑剔的美食家
    【贪心】BZOJ3668-[NOI2014]起床困难综合症
    【多重背包小小的优化(。・∀・)ノ゙】BZOJ1531-[POI2005]Bank notes
    【可持久化并查集】BZOJ3673-可持久化并查集 by zky
    【manacher+FFT】BZOJ3160-万径人踪灭
    SCOI2008着色方案(记忆化搜索)
    [JSOI2008]魔兽地图(树形dp)
    NOI2017蔬菜(贪心)
  • 原文地址:https://www.cnblogs.com/byghui/p/3076398.html
Copyright © 2011-2022 走看看