【精华】Android面试精华总结——Service组件

一、Service简介

  Service通常位于后台运行,一般不需要和用户交互,因此Service组件没有图形用户界面。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。组件可以绑定到服务,预支进行交互,甚至执行进程间通信(IPC)。例如,服务可以处理网络事务、播放音乐、执行文件I/O或与内容提供程序交互,所有这一切均可在后台进行。

二、 Service启动方式

1.调用startService启动

访问者与Service间没有关联,即使访问者退出了,Service也仍然在运行。不能调用Service内部的方法。

start() \rightarrow stop()

2.调用bindService启动

访问者与Service绑定在一起,访问者一旦退出,Service也就终止了。可以通过调用Service内部的方法。可以提供组件与Service交互的接口,进行跨进程通信(IPC)。
多可组件可以同时绑定到该服务,但全部取消绑定后该服务即被销毁。

bind() \rightarrow unbind()

3.混合启动模式

该方式保证了Service可长期在后台运行,还可让调用者远程调用Service中提供的方式。
只需要在服务中实现两个回调方法,即onStartCommand()允许组件开启服务,onBind()允许绑定。

start() \rightarrow bind() \rightarrow unbind() \rightarrow stop()

三、Service生命周期

在这里插入图片描述
  可以通过调用stopSelf()自行停止运行,其他组件也可以通过调用stopService()停止服务。服务停止后,系统会将其销毁。

四、Service与线程

  如需在主线程外部执行工作,且只是在用户正与应用交互时才有此需要,则应创建新线程而非服务。例如,只想在Activity运行的同事播放一些音乐,则可在onCreate()中创建线程, 在onStart()中启动线程,然后在onStop()中停止线程。
  服务在其托管进程的主线程中运行,它既不创建自己的线程,也不在单独的进程中运行。 如果服务将执行任何CPU密集型工作或阻止性操作,则应在服务内创建新线程来完成这项工作。通过使用单独的线程,可以降低发生ANR错误的风险,而应用的主线程仍可继续专注于运行用户与Acitity之间的交互。

五、IntentService

  Service本身存在两个问题:

(1)不会专门启动一个单独的线程
(2)不应在Service中直接处理耗时任务

  IntentService是Service的子类,使用队列来管理请求Intent,每当客户端代码通过Intent请求启动IntentService时,IntentService会将该Intent加入队列中,然后开启一条新worker线程处理该Intent。对于异步的startService请求,IntentService会按次序依次处理丢列中的Intent,该线程保证同一时刻只处理一个Intent。IntentService不会阻塞主线程,可以自己处理耗时任务。

  扩展IntentService只要重写onHandlerIntent()方法即可。

  IntentService具有如下特征:

  • IntentService会创建单独的worker线程来处理所有Intent请求;
  • IntentService会创建单独的worker线程处理onHandlerIntent()方法实现的代码,开发者无须处理多线程问题;
  • 当所有请求处理完后,IntentService会自动停止,故开发者无须调用stopself()方法停止Service;
  • 为Service的onBind()方法提供了默认实现,默认实现的onBind()方法返回null;
  • 为Service的onStartCommand()方法提供了默认实现,该实现会将请求Intent添加到队列中。
public class DataIntentService extends IntentService{
	public DataIntentService(){
		super("DataIntentService");
	}
	@Override
	protected void onHandleIntent(Intent intent){
		readData();
	}
}

六、前台服务

  前台服务被认为是用户主动意识到的一种服务,因此在内存不足时系统也不会考虑将其终止。前台服务必须为状态栏提供通知,这意味着除非服务停止或从前台移除,否则不能清除通知。
  要请求让服务运行于前台,需调用startForeground()。此方法有两个参数,即唯一标识通知的整型数和状态栏的Notification。

Notification notification = new Notification(R.drawable.icon,
				getText(R.string.ticker_text),System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
				getText(R.string.notification_message),pendingIntent());
startForeground(ONGOING_NOTIFICATION_ID, notification);	
												

·注:提供给startForeground()的整型ID不得为0。

  要从前台移除服务,需调用stopForeground()。此方法使用一个布尔值,指示是否移除状态栏通知,但不会停止服务。如果当服务正在前台运行时将其停止,则通知也会被移除。
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

  
  
  
  
  
  
  
  
  
  

发布了123 篇原创文章 · 获赞 119 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/cbwem/article/details/89761634