Android Service详解

转载请注明:http://blog.csdn.net/ly20116/article/details/50972910

Service详解
一、定义
Android四大组件之一,是一个可以在后台执行长时间运行操作而不使用用户界面的应用组件。服务能够被其他组件启动、绑定、交互、通信。
二、基本类型
1、Started(启动)
通过startService()方法启动的Service。通常,started的服务执行单一的操作并且不会向调用者返回结果。
2、Bound(绑定)
通过bindService()方法绑定的Service。bound服务提供了一个客户端/服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至可以利用进程间通信(IPC)跨进程执行这些操作。绑定服务的生存期和被绑定的应用程序组件一致。 多个组件可以同时与一个服务绑定,不过所有的组件解除绑定后,服务也就会被销毁。

注:服务运行于宿主进程的主线程中,耗时操作需要新建线程。
三、Service的生命周期
Android Service详解_第1张图片
1、onCreate()
首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。如果服务已在运行,则不会调用此方法。
2、onStartCommand()
通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法,服务即会启动并可在后台无限期运行。通过调用 stopSelf() 或 stopService() 来停止服务。
3、onBind()
通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。
4、onUnbind()
当Service上绑定的所有客户端都断开连接时调用此方法。
5、onDestroy()
当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。

完整生命周期 onCreate()->onDestroy()
有效生命周期 onStartCommand()–>完整生命周期结束
或onBind()–>onUnBind()

四、创建服务,扩展Service或IntentService
1、Service类
这是适用于所有服务的基类。扩展此类时,必须创建一个用于执行所有服务工作的新线程,因为默认情况下,服务将使用应用的主线程,这会降低应用正在运行的所有 Activity 的性能.
实现:

public class HelloService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    }

    @Override
    @Deprecated
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        super.onStart(intent, startId);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        return super.onUnbind(intent);
    }

}

2、IntentService类
这是 Service 的子类,它使用工作线程逐一处理所有启动请求。如果您不要求服务同时处理多个请求,这是最好的选择。 您只需实现 onHandleIntent() 方法即可,该方法会接收每个启动请求的 Intent,使您能够执行后台工作。
特点:
1、IntentService会创建单独的Worker线程处理所有的Intent请求;
2、IntentService会创建单独的worker线程来处理onHandleIntent()方法实现的代码,因此无需处理多线程问题;
3、所有请求处理完成后,IntentService自动停止。无需调用stopSelf()方法停止该Service;
4、service的onBind()方法提供了默认实现,返回null;
5、service的onStartCommand()方法提供了默认实现,该实现会将请求Intent添加到队列中。
使用方法:扩展IntentService重写onHandlerIntent()方法。

public class HelloIntentService extends IntentService {

  /** 
   * 构造方法是必需的,必须用工作线程名称作为参数
   * 调用父类的[http://developer.android.com/reference/android/app/IntentService.html#IntentService(java.lang.String) IntentService(String)]构造方法。
   */
  public HelloIntentService() {
      super("HelloIntentService");
  }

  /**
   * IntentService从缺省的工作线程中调用本方法,并用启动服务的intent作为参数。 
   * 本方法返回后,IntentService将适时终止这个服务。
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // 通常我们会在这里执行一些工作,比如下载文件。
      // 作为例子,我们只是睡5秒钟。
      long endTime = System.currentTimeMillis() + 5*1000;
      while (System.currentTimeMillis() < endTime) {
          synchronized (this) {
              try {
                  wait(endTime - System.currentTimeMillis());
              } catch (Exception e) {
              }
          }
      }
  }
}

五、启动和结束服务

1、启动服务
通过调用startService()方法或bindService()方法启动服务

Intent intent = new Intent(this, HelloService.class);
startService(intent);

2、结束服务
服务必须通过调用stopSelf()自行终止,或者其它组件可通过调用stopService()来终止它。如果服务是绑定的,则调用unbindService()方法解除绑定。

Intent intent = new Intent(this, HelloService.class);
stopService(intent);

六、bound服务(绑定服务、解除绑定、绑定服务的生命周期)
bound服务是指允许被应用程序组件绑定的服务,通过调用bindService()可以完成绑定,用于创建一个长期存在的连接。应用程序中的activity或其它组件需要与服务进行交互,或者应用程序的某些功能需要暴露给其它应用程序时,你应该创建一个bound服务,并通过进程间通信(IPC)来完成。
1、绑定服务
bindService(Intent service, ServiceConnection conn, int flags)
参数:
service:通过Intent指定要启动的service
conn:一个ServiceConnection对象,用于监听访问者与Service之间的连接情况。
flags:指定绑定时是否自动创建Service,可指定为0(不自动创建)或BIND_AUTO_CREATE(自动创建)

步骤:
1、在扩展的Service中,创建一个Binder的实例,其中实现以下三者之一:
(1)包含了可供客户端调用的公共方法
(2)返回当前Service实例,其中包含了可供客户端调用的公共方法。
(3)或者,返回内含服务类的其它类的一个实例,服务中包含了可供客户端调用的公共方法。
2、从回调方法onBind()中返回Binder的该实例。
3、在客户端中,在回调方法onServiceConnected()中接收Binder并用所提供的方法对绑定的服务进行调用

public class LocalService extends Service {
    // 给客户端的Binder
    private final IBinder mBinder = new LocalBinder();
    // 生成随机数
    private final Random mGenerator = new Random();

    /**
     * 用于客户端Binder的类。
     * 因为知道本服务总是运行于与客户端相同的进程中,我们就不需要用IPC进行处理。
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /** method for clients */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}
public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 绑定到LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 与服务解除绑定
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    /** 当按下按钮时调用(该按钮在layout文件中利用android:onClick属性与本方法关联 */
    public void onButtonClick(View v) {
        if (mBound) {
            // 调用LocalService中的方法。
            // 不过,如果该调用会导致某些操作的挂起,那么调用应该放入单独的线程中进行,
            // 以免降低activity的性能。
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

    /** 定义服务绑定时的回调方法,用于传给bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // 我们已经绑定到LocalService了,对IBinder进行类型转换(cast)并获得LocalService对象的实例
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

2、绑定服务的生命周期运行逻辑:
Android Service详解_第2张图片
一旦服务被所有客户端解除绑定,则Android系统将会销毁它,除非它同时又是用onStartCommand()started。
如果你选择实现onStartCommand()回调方法,那么你就必须显式地终止服务,因为此服务现在已经被视为started了。这种情况下,无论是否还存在客户端与其绑定,此服务都会运行下去,直至自行用stopSelf()终止或由其它组件调用stopService()来终止。
此外,如果你的服务是started且允许被绑定,那么系统调用你的onUnbind()方法时,你可以选择返回true。这样作的结果就是,下次客户端绑定时将会收到onRebind()调用(而不是收到onBind()调用)。onRebind()返回void,但客户端仍然能在它的onServiceConnected()回调方法中收到IBinder
3、解除绑定
调用unbindService()方法解除绑定。
unbindService(ServiceConnection conn)

你可能感兴趣的:(android进阶)