Android四大组件之一Service

Android四大组件之一Service

八月 06, 2019

Service

1、什么是Service?

Service是Android中经常使用组件之中的一个,它是Android中实现程序后台执行的解决方式,它非常适
合用于去执行那些不须要和用户交互且还要长期执行的任务。

这里的后台并非子线程的意思。Service默认并不会执行在子线程中。它也不会执行在一个独立的进程
中,它相同执行在UI线程中,因此,不要在Service中执行耗时的操作。假设须要执行耗时的操作,能够
在Service中创建子线程来完毕耗时操作。

Service的执行不依赖于不论什么用户界面,及时程序被切换到后台或者用户打开了另外一个应用程序,
Service仍然能够保持正常执行。这也正式Service的使用场景。

当某个应用程序进程被杀掉时,全部依赖于该进程的Service也会停止执行。

2、Service 是否在 main thread 中执行, service 里面是否能执行耗时的操作?

默认情况,如果没有显示的指 service 所运行的进程, Service 和 activity 是运行在当前 app 所在
进程的 main thread(UI 主线程)里面。

service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )

特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另外的进程中执行

1
2
3
4
5
<service 
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
</service>

3、Activity 和 Service 绑定,怎么在 Activity 中启动自己对应的 Service

Activity 通过 bindService(Intent service, ServiceConnection conn, int flags)跟
Service 进行绑定,当绑定成 功的时候 Service 会将代理对象通过回调的形式传给 conn,这样我们就
拿到了 Service 提供的服务代理对象。

在 Activity 中可以通过 startService 和 bindService 方法启动 Service。一般情况下如果想获
取 Service 的服务 对象那么肯定需要通过 bindService()方法,比如音乐播放器,第三方支付等。
如果仅仅只是为了开启一个后台任 务那么可以使用 startService()方法。

4、Service 的生命周期

Service 有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不同的使用方法生命周期方法也不
同。

非绑定模式:当第一次调用 startService 的时候执行的方法依次为 onCreate()、onStartCommand()
,(onStart()) 当 Service 关闭的时候调用 onDestory 方法。

绑定模式:第一次 bindService()的时候,执行的方法为 onCreate()、onBind()解除绑定的时候会
执行 onUnbind()、onDestory()。

上面的两种生命周期是在相对单纯的模式下的情形。我们在开发的过程中还必须注意 Service 实例只会
有一个, 也就是说如果当前要启动的 Service 已经存在了那么就不会再次创建该 Service 当然也不会
调用 onCreate()方法。

一个 Service 可以被多个客户进行绑定,只有所有的绑定对象都执行了 onBind()方法后该
Service 才会销毁, 不过如果有一个客户执行了 onStart()方法,那么这个时候如果所有的 bind 客
户都执行了 unBind()该 Service 也不会 销毁。

5、什么是 IntentService 以及 IntentService 的优点

一、IntentService 简介

IntentService 是 Service 的子类,比普通的 Service 增加了额外的功
能。先看 Service 本身存在两个问题: Service 不会专门启动一条单独的进程,Service 与它所在应
用位于同一个进程中; Service 也不是专门一条新线程,因此不应该在 Service 中直接处理耗时的任
务;

二、IntentService 特征

会创建独立的 worker 线程来处理所有的 Intent 请求; 会创建独立的 worker 线程来处理
onHandleIntent()方法实现的代码,无需处理多线程问题; 所有请求处理完成后,IntentService 会
自动停止,无需调用 stopSelf()方法停止 Service; 为 Service 的 onBind()提供默认实现,返回
null; 为 Service 的 onStartCommand 提供默认实现,将请求 Intent 添加到队列中;

三、使用 IntentService

本人写了一个 IntentService 的使用例子供参考。该例子中一个 MainActivity 一个
MyIntentService,这两 个类都是四大组件当然需要在清单文件中注册。这里只给出核心代码:

MainActivity.java:

1
2
3
4
5
public void click(View view) {
Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra("start", "MyIntentService");
startService(intent);
}

MyIntentService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class MyIntentService extends IntentService { 

private String ex = ""

private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
Toast.makeText(MyIntentService.this, "-e " + ex Toast.LENGTH_LONG).show();
}
};

public MyIntentService(){
super("MyIntentService");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
ex = intent.getStringExtra("start");
return super.onStartCommand(intent, flags, startId);
}

@Override
protected void onHandleIntent(Intent intent) {
/*** 模拟执行耗时任务 * 该方法是在子线程中执行的,因此需要用到 handler 跟主线
程进行通信 */
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

mHandler.sendEmptyMessage(0);

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

6、Activity、Intent、Service 的关系

他们都是 Android 开发中使用频率最高的类。其中 Activity 和 Service 都是 Android 四大组件之
一。他俩都是 Context 类的子类 ContextWrapper 的子类,因此他俩可以算是兄弟关系吧。不过兄弟
俩各有各自的本领,Activity 负责用户界面的显示和交互,Service 负责后台任务的处理。Activity
和 Service 之间可以通过 Intent 传递数据,因此 可以把 Intent 看作是通信使者。

7、Service 和 Activity 是否在同一个线程

对于同一 app 来说默认情况下是在同一个线程中的,main Thread (UI Thread)。

8、Service 里面是否可以弹吐司

可以的。弹吐司有个条件就是得有一个 Context 上下文,而 Service 本身就是 Context 的子类,因
此在 Service 里面弹吐司是完全可以的。比如我们在 Service 中完成下载任务后可以弹一个吐司通知
用户。

9、让一个 Service 成为前置进程

在启动该 Service 的时候可以在添加上如下方法:

1
2
3
4
5
6
7
8
9
10
11
@Override 
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = new Notification(R.drawable.ic_launcher, "服务正
在运行",System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent,0);
notification.setLatestEventInfo(this,"消息标题","消息内容", pendingIntent);
startForeground(1, notification); return super.onStartCommand(intent, flags,
startId);
}

10、Service 的 onStartCommand 方法的返回值

有四种返回值,不同值代表的意思如下:

START_STICKY:如果 service 进程被 kill 掉,保留 service 的状态为开始状态,但不保留递送的
intent 对象。随 后 系 统 会 尝 试 重 新 创 建 service , 由 于 服 务 状 态 为 开 始 状
态 , 所 以 创 建 服 务 后 一 定 会 调 用 onStartCommand(Intent,int,int)方法。如果在此期
间没有任何启动命令被传递到 service,那么参数 Intent 将为 null。

START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完 onStartCommand 后,服务被异
常 kill 掉,系统不会自动重启该服务。

START_REDELIVER_INTENT:重传 Intent。使用这个返回值时,如果在执行完 onStartCommand 后,
服务被异常 kill 掉,系统会自动重启该服务,并将 Intent 的值传入。

START_STICKY_COMPATIBILITY:START_STICKY 的兼容版本,但不保证服务被 kill 后一定能重启。

11、Service 的 onRebind(Intent)方法在什么情况下会执行

如果在 onUnbind()方法返回 true 的情况下会执行,否则不执行。

官方解释如下:

1
2
3
Called when new clients have connected to the service, after it had previously 
been notified that all had disconnected in its onUnbind. This will only be
called if the implementation of onUnbind was overridden to return true.