1、什么是Service
2、Service的生命周期
3、Service的工作过程
4、Service的start和bind状态有什么区别?
5、同一个Service,先startService,然后再bindService,如何把它停止掉?
6、你有注意到Service的onStartCommand方法的返回值吗?不同返回值有什么区别?
7、Service的生命周期方法onCreate、onStart、onBind等运行在哪个线程?

1.什么是service?

服务是一种应用程序组件,表示应用程序希望在不与用户交互的情况下执行长时间运行的操作,或者为其他应用程序提供的功能。每个服务类必须在其包的AndroidManifest.xml中具有相应的<service>声明。服务可以使用Context.startService()和Context.bindService()来启动。 请注意,与其他应用程序对象一样,服务在主机进程的主线程中运行。这意味着,如果你的服务要做任何CPU密集型(如MP3播放)或阻塞(如网络)操作,它应该产生自己的线程来完成这项工作。有关这方面的更多信息可以在“进程和线程”中找到。 IntentService类可作为Service的标准实现提供,它具有自己的线程,用于调度要完成的工作。

2.Service 的生命周期

Service有两种启动方式:

调用Context.startService(),那么系统将检索服务(如果需要,创建它并调用它的onCreate()方法),然后使用客户端提供的参数调用它的onStartCommand(Intent,int,int)方法。此服务将继续运行,直到调用Context.stopService()或stopSelf()。请注意,对Context.startService()的多次调用不会嵌套(尽管它们会导致对onStartCommand())进行多次相应调用),因此无论启动多少次,服务都会停止一次Context.stopService()或stopSelf () ;然而,服务可以使用他们的stopSelf(int)方法来确保服务不会停止,直到处理完启动的意图为止。对于已启动的服务,根据从onStartCommand()返回的值,他们可以决定运行两个额外的主要操作模式:START_STICKY用于根据需要显式启动和停止的服务,而使用START_NOT_STICKY或START_REDELIVER_INTENT对于在处理发送给它们的任何命令时应该只保持运行的服务。

调用Context.bindService()来获得到服务的持久连接。如果服务尚未运行(同时调用onCreate()),则同样会创建服务,但不会调用onStartCommand()。客户端将收到服务从其onBind(Intent)方法返回的IBinder对象,从而允许客户端将该服务调用回该服务。只要建立连接(无论客户是否保留对服务的IBinder的引用),该服务就会继续运行。返回的IBinder通常是用于一个复杂的接口,已经被写入aidl。
服务既可以启动,也可以绑定连接。在这种情况下,只要系统启动,或者存在与Context.BIND_AUTO_CREATE标志的一个或多个连接,系统就会继续运行该服务。一旦这些情况都不成立,就会调用服务的onDestroy()方法,并且服务被有效终止。从onDestroy()返回后,所有清理(停止线程,取消注册接收者)应该完成。

3.Service的工作过程

Service分为两种工作状态:一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和service的交互。service的两种状态是可以共存的,那么Service既可以处于启动状态也可以处于绑定状态。

启动状态:

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

 bindService(intent,conn,BIND_AUTO_CREATE);

service的启动过程

1.startService(intent);
我们看一下 service的源码 :package android.app.Service;

public abstract class Service extends ContextWrapper implements ComponentCallbacks2
Service 继承了ContextWrapper ,service的启动过程是从ContextWrapper 的startService开始
  @Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}

通过mBase,调用startService

public class ContextWrapper extends Context {
Context mBase; public ContextWrapper(Context base) {
mBase = base;
}

而Context类是个abstract

public abstract class Context
Activity被创建时会通过attach方法将一个ContextImpl对象关联起来,ContextImpl 实现了Context,mBase 的类型就是ContextImpl ,ContextWrapper 大部分操作都是通过mBase 完成的,这是一种典型的桥接模式。
startService 是通过Context调用的,那我们看下ContextImpl 是如何实现startService 的。
  @Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
} private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
// 开启服务 ActivityManagerNative.getDefault() 其实就是 ActivityManagerService(AMS)
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

简单说一下 ActivityManagerNative

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
} return new ActivityManagerProxy(obj);
} /**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
} private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};

public final class ActivityManagerService extends ActivityManagerNative
ActivityManagerService 是继承ActivityManagerNative的 AMS启动服务是一个远程调用过程,更具体的实现过程大家可以看源码,这里就不在长篇幅的写源码的启动过程了。
2.bindService 的绑定过程同样在ContextImpl 中,大家可自行翻阅理解。

4.Service的start和bind状态有什么区别?

start启动的service,不依赖组件,有独立的生命周期多次调用service不会嵌套,尽管会对onStartCommand()多次调用,因此无论启动多少次,服务都会停止一次Context.stopService()或stopSelf ()(IntentService会自动调用一次onStopSelf).然而,服务可以使用他们的stopSelf(int)方法来确保服务不会停止,直到处理完启动的意图为止。对于已启动的服务,根据从onStartCommand()返回的值,他们可以决定运行两个额外的主要操作模式:START_STICKY用于根据需要显式启动和停止的服务,而使用START_NOT_STICKY或START_REDELIVER_INTENT对于在处理发送给它们的任何命令时应该只保持运行的服务。

bind绑定的service依赖于组件,组件销毁service也随之销毁,需要注意的比如在Activity中bind了service,那么必须在onDestory方法中销毁service调用unBindServie方法。多次调用bind方法只会调用一次onBind()方法,但不会调用onStartCommand()。停止服务是调用了n次bindService,就必须要调用n次unBindService.

5.同一个Service,先startService,然后再bindService,如何把它停止掉?

startService 不论调用几次,只需要stopService(或stopSelf) 一次即可停止掉服务。
如果调用了n次bindService,必须调用n次unBindService 方法,才能停止掉服务。
执行的顺序没有要求。
最后一个stopService(或stopSelf)或者unBindService方法会导致Service的onDestroy方法执行。

6. Service的onStartCommand方法的返回值?不同返回值有什么区别?

一共有四种返回值
START_STICKY_COMPATIBILITY,
START_STICKY,
START_NOT_STICKY,
START_REDELIVER_INTENT,

 /**
*不保证的{@link #START_STICKY}版本
* {@link #onStartCommand}在被杀后会再次被调用。
*为了兼容版本,在service被杀死后,并不保证onStartCommand 会被再次调用
*/
public static final int START_STICKY_COMPATIBILITY = 0; /**
* 如果此service是进程在启动时被杀死(返回后),保持启动状态,但不保留Intent ,之后系统会尝试重启该service,并重新回调
* onStartCommand方法,如果没有其他的start命令,会传递给service 的intent为null,需要注意onStartCommand方法对intent的非空判断
*/
public static final int START_STICKY = 1; /**
* 常规操作,除非死之前还有组件调用startService,否则系统不会保留启动状态并重启该service
*/
public static final int START_NOT_STICKY = 2; /**
* service 被杀死后,系统会组织一次service重启(除非之前调用了stopSelf)被杀死之前最后一次传递的intent将被执行,该flag将不会传递空intent,
*这适用于那些应该立即恢复正在执行的工作的服务,如下载文件。
*/
public static final int START_REDELIVER_INTENT = 3;

7.Service的生命周期方法onCreate、onStart、onBind等运行在哪个线程?

Service 默认是运行在主线程的,并且其生命周期也是运行在主线程的,所以要想在service中执行耗时操作必须另起一个Thread线程(或者使用IntentService),否则会ANR.

 
 
=======================转==========================
作者:JakePrim
链接:https://www.jianshu.com/p/087415add7a5
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

深入理解Android-清晰的理解Service的更多相关文章

  1. [转载] 深入理解Android之Java虚拟机Dalvik

    本文转载自: http://blog.csdn.net/innost/article/details/50377905 一.背景 这个选题很大,但并不是一开始就有这么高大上的追求.最初之时,只是源于对 ...

  2. [深入理解Android卷一全文-第三章]深入理解init

    因为<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该因为纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的全部内容. ...

  3. 《深入理解Android 卷III》第四章 深入理解WindowManagerService

    <深入理解Android 卷III>即将公布,作者是张大伟.此书填补了深入理解Android Framework卷中的一个主要空白.即Android Framework中和UI相关的部分. ...

  4. [深入理解Android卷一全文-第十章]深入理解MediaScanner

    由于<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该由于纸质媒介的问题而中断.所以我将在CSDN博客中全文转发这两本书的全部内容. ...

  5. 《深入理解Android 卷III》第六章 深入理解控件(ViewRoot)系统

    <深入理解Android 卷III>即将公布,作者是张大伟.此书填补了深入理解Android Framework卷中的一个主要空白,即Android Framework中和UI相关的部分. ...

  6. (转载)你真的理解Android AIDL中的in,out,inout么?

    前言 这其实是一个很小的知识点,大部分人在使用AIDL的过程中也基本没有因为这个出现过错误,正因为它小,所以在大部分的网上关于AIDL的文章中,它都被忽视了——或者并没有,但所占篇幅甚小,且基本上都是 ...

  7. 安卓学习资料推荐《深入理解Android:卷2》下载

    下载地址:百度云下载地址 编辑推荐 <深入理解Android:卷2>编辑推荐:经典畅销书<深入理解Android:卷I>姊妹篇,51CTO移动开发频道和开源中国社区一致鼎力推荐 ...

  8. 深入理解 Android 之 View 的绘制流程

    概述 本篇文章会从源码(基于Android 6.0)角度分析Android中View的绘制流程,侧重于对整体流程的分析,对一些难以理解的点加以重点阐述,目的是把View绘制的整个流程把握好,而对于特定 ...

  9. [译]:Xamarin.Android开发入门——Hello,Android Multiscreen深入理解

    原文链接:Hello, Android Multiscreen_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android Multiscreen深入理解. 本 ...

  10. Android动画的理解

    基础知识 在我们开始讲Android动画这个知识点之前,我们了解下相应的基础知识点. Shape篇 一般用Shape定义的XML文件是存放在Drawable目录下,广泛应用于在Button.TextV ...

随机推荐

  1. SOLID设计原则

    SOLID设计原则 Single Responsibility Principle单一职责原则 单一职责原则(SRP)表明一个类有且只有一个职责. 一个类就像容器一样,它能添加任意数量的属性.方法等. ...

  2. Spring中使用到的设计模式

    1.工厂模式:Beanfactory和ApplicationContext 2.单例模式:bean的构建 3.代理模式:AOP 4.模板模式:jdbcTemplate,hibernateTemplat ...

  3. 安装percona-toolkit.rpm时候报错:perl(Time::HiRes) is needed by percona-toolkit-2.2.16-1.noarch

    1.安装percona-toolkit.rpm时候报错: warning: percona-toolkit.rpm: Header V4 DSA/SHA1 Signature, key ID cd2e ...

  4. 【luoguP3701】「伪模板」主席树

    description byx和诗乃酱都非常都非常喜欢种树.有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家种树,并约定几年后比一比谁种出来的树更加牛x. 很快,这棵树就开花结果了.byx和诗乃 ...

  5. php 简单的工程模式 实现加法操作

    class A{ protected $Num1; protected $Num2; public $result; public function getNum1(){ return $this-& ...

  6. 牛客多校第三次B——线段树维护线性基交

    写线性基交函数时调试了半天.. #include<bits/stdc++.h> using namespace std; #define ll long long #define maxn ...

  7. NX二次开发-查询信息窗口是否打开UF_UI_is_listing_window_open

    #include <uf.h> #include <uf_ui.h> UF_initialize(); //打开信息窗口 UF_UI_open_listing_window() ...

  8. 使用Docker在服务器上部署Ubuntu,本地传文件到docker

    使用Docker在服务器上部署Ubuntu,本地传文件到docker 作者:王佳乐 目录 安装Docker 安装Docker 全部安装流程: 登录服务器 ssh username@ip 检查是否已经安 ...

  9. Java-Class-@I:org.apache.ibatis.annotations.Mapper

    ylbtech-Java-Class-@I:org.apache.ibatis.annotations.Mapper 1.返回顶部   2.返回顶部 1. package com.ylbtech.ed ...

  10. JavaScript学习总结(七)——ECMAScript6(ES6)

    一.ECMAScript概要 ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通 ...