前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(四十一)Service的生命周期

Android开发笔记(四十一)Service的生命周期

作者头像
aqi00
发布2019-01-18 10:41:09
4300
发布2019-01-18 10:41:09
举报
文章被收录于专栏:老欧说安卓老欧说安卓

与生命周期有关的方法

onCreate : 创建服务 onStart : 开始服务,Android2.0以下版本使用 onStartCommand : 开始服务,Android2.0及以上版本使用。该函数返回值为整型,一般取值START_STICKY,具体说明如下: 1、START_STICKY:粘性的服务。如果服务进程被杀掉,保留服务的状态为开始状态,但不保留传送的Intent对象。随后系统会尝试重新创建服务,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand方法。如果在此期间没有任何启动命令送给服务,那么参数Intent将为空值。 2、START_NOT_STICKY:非粘性的服务。使用这个返回值时,如果服务被异常杀掉,系统不会自动重启该服务。 3、START_REDELIVER_INTENT:重传Intent的服务。使用这个返回值时,如果服务被异常杀掉,系统会自动重启该服务,并传入Intent的原值。 4、START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被杀掉后一定能重启。 onDestroy : 销毁服务 onBind : 绑定服务 onRebind : 重新绑定。该方法只有当onUnbind返回true的时候才会被调用 onUnbind : 解除绑定。返回值true表示希望以后再绑定时能够调用onRebind方法,false表示再绑定时不调用onRebind方法 最简单的服务启动顺序:onCreate->onStartCommand 最简单的服务退出顺序:onDestroy

Service的生命周期流程

单独启停服务

启动服务,方法调用顺序为:onCreate->onStartCommand。日志如下: 01-06 17:25:14.309: D/FirstService(1604): onCreate 01-06 17:25:14.309: D/FirstService(1604): onStartCommand 停止服务,方法调用顺序为:onDestroy。日志如下: 01-06 17:25:30.485: D/FirstService(1604): onDestroy 已启动的服务再次启动,方法调用顺序为:onStartCommand。日志如下: 01-06 17:25:47.097: D/FirstService(1604): onStartCommand

单独绑定服务

直接绑定服务,方法调用顺序为:onCreate->onBind。日志如下: 01-07 09:13:12.521: D/FirstService(1360): onCreate 01-07 09:13:12.521: D/FirstService(1360): onBind 解绑服务,方法调用顺序为:onUnbind->onDestroy。日志如下: 01-07 09:13:31.905: D/FirstService(1360): onUnbind 01-07 09:13:31.905: D/FirstService(1360): onDestroy

先启动服务再绑定服务

启动服务,方法调用顺序为:onCreate->onStartCommand。日志如下: 01-07 10:47:53.685: D/FirstService(5486): onCreate 01-07 10:47:53.685: D/FirstService(5486): onStartCommand 接着绑定服务,方法调用顺序为:onBind。日志如下: 01-07 10:47:55.401: D/FirstService(5486): onBind 接着解绑服务,方法调用顺序为:onUnbind。日志如下: 01-07 10:47:59.565: D/FirstService(5486): onUnbind 接着再次绑定服务,方法调用顺序为:onRebind。日志如下: 01-07 10:48:03.109: D/FirstService(5486): onRebind

日志观察结果

从上面日志可以看出 1、在启动服务时,Android2.0及以上版本只调用onStartCommand方法,不调用onStart方法。 2、绑定服务时,只调用onBind方法或者onRebind方法,不调用onStart和onStartCommand方法。 3、通过startService启动服务后调用bindService绑定服务,此时解绑服务并不会销毁服务,解绑后再次绑定,调用的是onRebind方法而不是onBind方法。

Service的启停方式

外部启动和停止

类似Activity的启停,先声明一个Intent对象指定跳转的路径与数据,然后调用启动方法startService,停止则调用方法stopService。代码示例如下: 启动服务

代码语言:javascript
复制
		Intent mFirstIntent = new Intent(MainActivity.this, FirstService.class);
		startService(mFirstIntent);

停止服务

代码语言:javascript
复制
		stopService(mFirstIntent);

外部绑定和解绑

绑定前需要实现一个服务连接接口ServiceConnection,代码示例如下:

代码语言:javascript
复制
	private SecondService mSecondService;
	private ServiceConnection mConn = new ServiceConnection() {
	    /** 获取服务对象时的操作 */
	    public void onServiceConnected(ComponentName name, IBinder service) {
	    	mSecondService = ((SecondService.LocalBinder) service).getService();
	    }
	
	    /** 无法获取到服务对象时的操作 */
	    public void onServiceDisconnected(ComponentName name) {
	    	mSecondService = null;
	    }
	
	};

绑定服务

代码语言:javascript
复制
		Intent mSecondIntent = new Intent(MainActivity.this, SecondService.class);
		bindService(mSecondIntent, mConn, Context.BIND_AUTO_CREATE);

解绑服务

代码语言:javascript
复制
		if (mSecondService != null) {
			unbindService(mConn);
			mSecondService = null;
		}

Service内部启停

一般的服务停止可调用方法stopSelf(),不过Service实例因各种缘由常常会被系统杀掉(系统资源不足、服务挂起、用户退出Activity等等),像我们用手机听音乐,可不希望听一半就没声音了,所以这时我们要想办法保持播放音乐。startForeground便是这样一个方法,它在通知栏挂上服务的一条信息,从而让服务在前台运行,就不会被系统杀掉。startForeground方法可在onStartCommand中调用,对应的停止方法stopForeground可在onDestroy中调用,示例代码如下:

代码语言:javascript
复制
	@Override
	public void onDestroy() {
		Log.d(TAG, "onDestroy");
		stopForeground(true);			//true表示清除通知,false表示不清除
		super.onDestroy();
	}


	@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
	@Override
	public int onStartCommand(Intent intent, int flags, int startid) {
		Log.d(TAG, "onStartCommand. flags="+flags);
		
		Intent actIntent = new Intent(this, MainActivity.class);
		PendingIntent contentIntent = PendingIntent.getActivity(
				this,
				R.string.app_name,
				actIntent,
				PendingIntent.FLAG_UPDATE_CURRENT);
		Notification.Builder builder = new Notification.Builder(this);
		builder.setContentIntent(contentIntent)
				.setSmallIcon(R.drawable.ic_launcher)			//设置状态栏里面的图标(小图标))
				.setTicker("前台运行")							//设置状态栏的显示的信息
				.setWhen(System.currentTimeMillis())			//设置时间发生时间
				.setAutoCancel(true)							//设置可以清除
				.setContentTitle("啦啦啦")						//设置下拉列表里的标题
				.setContentText("我跑到前台,不怕被系统杀掉啦");//设置上下文内容
		Notification notify = builder.build();				//Android 4.1.2 及以上版本才支持该语句
		startForeground(1, notify);
		
		return START_STICKY;
	}

异步服务IntentService

Service虽然是后台服务,却跟Activity一样在主线程中,如果Service挂起,那么Activity页面也会死机。可是Service经常要做一些异步的操作,比如说网络访问请求等等,这样就不能拖累Activity。当然我们可以在Service中采取异步处理机制,比如说Thread+Handler等等,多写写代码都能实现。其实Android已经为我们考虑到了这种情况,所以提供了IntentService来处理。 IntentService是Service的子类,它通过Looper和Thread来解决Service中处理逻辑的阻塞问题。查看IntentService的源码,会发现其内部使用了线程HandlerThread,还使用了处理器ServiceHandler,相当于把Thread+Handler整套流程封装好了。具体需要异步操作的处理代码,我们直接重写onHandleIntent方法即可,确实是省了不少功夫。 使用IntentService与Service的代码区别如下: 1、新的服务类从继承Service改为继承IntentService; 2、增加一个构造方法,为的是给内部线程分配唯一名称,示例代码如下:

代码语言:javascript
复制
	private static final String TAG = "SecondService";
	public SecondService() {
		super(TAG);
		Log.d(TAG, "SecondService");
	}

3、重写onHandleIntent方法,把需要异步处理的代码写进去; 4、onStartCommand方法中记得调用父类的onStartCommand,因为Service类没有具体实现该方法但IntentService有具体实现,示例代码如下:

代码语言:javascript
复制
	@Override
	public int onStartCommand(Intent intent, int flags, int startid) {
		Log.i(TAG, "onStartCommand threadname = " + Thread.currentThread().getName()); 
		return super.onStartCommand(intent, flags, startid); 
	}

点击下载本文用到的Service生命周期的工程代码 点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年01月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 与生命周期有关的方法
  • Service的生命周期流程
    • 单独启停服务
      • 单独绑定服务
        • 先启动服务再绑定服务
          • 日志观察结果
          • Service的启停方式
            • 外部启动和停止
              • 外部绑定和解绑
                • Service内部启停
                • 异步服务IntentService
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档