Android Service

一、基础概念

Service是Android中一个类,它是Android四大组件之一,使用Service可以在后台执行长时间的操作( perform long-running operations in the background ),Service并不与用户产生UI交互。其他的应用组件可以启动Service,即便用户切换了其他应用,启动的Service仍可在后台运行。一个组件可以与Service绑定并与之交互,甚至是跨进程通信(IPC)。例如,一个Service可以在后台执行网络请求、播放音乐、执行文件读写操作或者与 content provider交互 等。

Services有两种启动形式:

  • Started:其他组件调用startService()方法启动一个Service。一旦启动,Service将一直运行在后台,即便启动Service的组件已被destroy。通常,一个被start的Service会在后台执行单独的操作,也并不给启动它的组件返回结果。比如说,一个start的Service执行在后台下载或上传一个文件的操作,完成之后,Service应自己停止。

  • Bound:其他组件调用bindService()方法绑定一个Service。通过绑定方式启动的Service是一个client-server结构,该Service可以与绑定它的组件进行交互。一个bound service仅在有组件与其绑定时才会运行,多个组件可与一个service绑定,service不再与任何组件绑定时,该service会被destroy。

请注意:Service运行在主线程中(A service runs in the main thread of its hosting process),Service并不是一个新的线程,也不是新的进程。也就是说,若您需要在Service中执行较为耗时的操作(如播放音乐、执行网络请求等),需要在Service中创建一个新的线程(强烈建议使用IntentService)。这可以防止ANR的发生,同时主线程可以执行正常的UI操作

二、代码说话-startService

新建类,继承Service,然后实现它的onBind()方法,同时重写它的几个方法打印下生命周期

  public class MyService extends Service {
  private static final String TAG = "dah_MyService";

@Override
public void onCreate() {
    super.onCreate();
    Log.e(TAG, "onCreate: ");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.e(TAG, "onStartCommand: ");
    return super.onStartCommand(intent, flags, startId);
}

@Override
public void onStart(Intent intent, int startId) {
    Log.e(TAG, "onStart: ");
    super.onStart(intent, startId);
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.e(TAG, "onBind: ");
    return null;
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.e(TAG, "onDestroy: ");
}

service作为四大组件之一,是需要在AndroidManifest.xml中注册的

<service android:name=".service.MyService"/>

在MainActivity中添加两个Button,分别调用startService、stopService方法(不上代码了)

     mBtnStartService.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(mContext, MyService.class);
            startService(intent);
        }
    });
    mBtnStopService.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(mContext, MyService.class);
            stopService(intent);
        }
    });

运行后,点击启动按钮,Log输入显示,依次调用了onCreate()->onStartCommand()->onStart(),

03-14 10:51:43.756 16073-16073/com.yanftch.basic E/dah_MyService: onCreate: 
03-14 10:51:43.756 16073-16073/com.yanftch.basic E/dah_MyService: onStartCommand: 
03-14 10:51:43.756 16073-16073/com.yanftch.basic E/dah_MyService: onStart: 

再次点击启动按钮,会发现只调用了onStartCommand()->onStart(),证实了onCreate()方法只会调用一次

03-14 10:51:43.756 16073-16073/com.yanftch.basic E/dah_MyService: onCreate: 
03-14 10:51:43.756 16073-16073/com.yanftch.basic E/dah_MyService: onStartCommand: 
03-14 10:51:43.756 16073-16073/com.yanftch.basic E/dah_MyService: onStart: 
03-14 10:53:10.323 16073-16073/com.yanftch.basic E/dah_MyService: onStartCommand: 
03-14 10:53:10.323 16073-16073/com.yanftch.basic E/dah_MyService: onStart: 

点击停止按钮,Log显示调用了onDestroy()方法,此时停止了Service

小结:

1.通过startService()启动Service,会依次调用onCreate()->onStartCommand()->onStart(),一旦Service启动成功,再次调用startService()时,只会调用onStartCommand()和onStart(),不会再调用onCreate(),也就是说onCreate()只会执行一次(该Service没有销毁时)。通过stopService()方法停止Service,会调用Service的onDestroy()方法。

2.onStartCommand()和onStart()的有什么关系。
在API 2.0之前,只有onStart()方法,而2.0之后,推荐使用onStartCommand()方法,其实onStartCommand()内部也是调用了onStart()方法,所以我们在开发中只重写onStartCommand()就可以了,而onStartCommand()方法的作用是告诉系统如何重启服务,如判断是否异常终止后重新启动,在何种情况下异常终止 等等。
3.在Service当中,如果有耗时操作,请开始子线程来执行

代码说话-bindService()
bindService(Intent service, ServiceConnection conn,int flags) 

第一个参数:Intent指示对应的Service对象;

第二个参数:实现了 ServiceConnection接口的对象,conn是一个代表与service连接状态的类,当我们连接service成功或失败时,会主动触发其内部的onServiceConnected或onServiceDisconnected方法。如果我们想要访问service中的数据,可以在onServiceConnected()方法中进行实现;

第三个参数:Flags,在进行服务绑定时,其标志位可以为BIND_AUTO_CREATE、BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND等。其中BIND_AUTO_CREATE表示当收到绑定请求时,如果服务尚未创建,则即刻创建,在系统内存不足,需要先销毁优先级组件来释放内存,且只有驻留该服务的进程成为被销毁对象时,服务才可被销毁;BIND_DEBUG_UNBIND通常用于调试场景中判断绑定的服务是否正确,但其会引起内存泄漏,因此非调试目的不建议使用;BIND_NOT_FOREGROUND表示系统将阻止驻留该服务的进程具有前台优先级,仅在后台运行


使用bindService()启动Service,这种模式是客户端-服务端模式(client-server),即服务端是Service,客户端是调用者,例如是某个Activity,客户端-服务端是可以相互通信的。

点击bind按钮,Log显示依次调用:onCreate–>onBind–>onServiceConnected
调用者和服务端已经绑定成功,建立连接。
如果再点一次,啥都没有,为啥?
我们在绑定Service的时候,如果service没被创建,那么调用一次onCreate(),然后调用onBind(),多次绑定时,不会多次调用onBind()。

点击unbind按钮,Log显示依次调用:onUnbind–>onDestroy
此时说明,Service已经停止了。细心的你,有没有发现有个方法没有调用?你知道是哪个方法吗?是—–>onServiceDisconnected()方法,为何我们解除绑定了,该回调方法没有调用呢?

03-14 11:21:37.711 21194-21194/com.yanftch.basic E/dah_MyBindService: onCreate: 
03-14 11:21:37.711 21194-21194/com.yanftch.basic E/dah_MyBindService: onBind: 
03-14 11:21:37.717 21194-21194/com.yanftch.basic E/dah_ServiceActivity: onServiceConnected: name===ComponentInfo{com.yanftch.basic/com.yanftch.basic.service.MyBindService}     service===com.yanftch.basic.service.MyBindService$MyBinder@1fb98d1d
03-14 11:22:56.421 21194-21194/com.yanftch.basic E/dah_MyBindService: onUnbind: 
03-14 11:22:56.422 21194-21194/com.yanftch.basic E/dah_MyBindService: onDestroy: 

startService()和bindService()启动Service的区别

Alt text

1.最经典的生命周期图,

2.两者和启动者的关系。

startService()启动的Service和启动者的生命周期无关,必须要显示调用stopService(intent)方法,才能停止该Service;

bindService()启动的Service和启动者的生命周期有关,当启动者销毁时,会自动销毁该Service。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值