不少Android初学者都可能会有这样的疑惑,Service和Thread到底有什么关系呢?什么时候应该用Service,什么时候又应该用Thread?答案可能会有点让你吃惊,因为Service和Thread之间没有任何关系!

之所以有不少人会把它们联系起来,主要就是因为Service的后台概念。Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。而Service我们最初理解的时候,总会觉得它是用来处理一些后台任务的,一些比较耗时的操作也可以放在这里运行,这就会让人产生混淆了。但是,如果我告诉你Service其实是运行在主线程里的,你还会觉得它和Thread有什么关系吗?让我们看一下这个残酷的事实吧。

在MainActivity的onCreate()方法里加入一行打印当前线程id的语句:

[java] view plaincopy
  1. Log.d("MyService", "MainActivity thread id is " + Thread.currentThread().getId());

然后在MyService的onCreate()方法里也加入一行打印当前线程id的语句:

[java] view plaincopy
  1. Log.d("MyService", "MyService thread id is " + Thread.currentThread().getId());

现在重新运行一下程序,并点击Start Service按钮,会看到如下打印日志:

可以看到,它们的线程id完全是一样的,由此证实了Service确实是运行在主线程里的,也就是说如果你在Service里编写了非常耗时的代码,程序必定会出现ANR的。

你可能会惊呼,这不是坑爹么!?那我要Service又有何用呢?其实大家不要把后台和子线程联系在一起就行了,这是两个完全不同的概念。Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。比如说一些应用程序,始终需要与服务器之间始终保持着心跳连接,就可以使用Service来实现。你可能又会问,前面不是刚刚验证过Service是运行在主线程里的么?在这里一直执行着心跳连接,难道就不会阻塞主线程的运行吗?当然会,但是我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。

额,既然在Service里也要创建一个子线程,那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

一个比较标准的Service就可以写成:

[java] view plaincopy
  1. @Override
  2. public int onStartCommand(Intent intent, int flags, int startId) {
  3. new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. // 开始执行后台任务
  7. }
  8. }).start();
  9. return super.onStartCommand(intent, flags, startId);
  10. }
  11. class MyBinder extends Binder {
  12. public void startDownload() {
  13. new Thread(new Runnable() {
  14. @Override
  15. public void run() {
  16. // 执行具体的下载任务
  17. }
  18. }).start();
  19. }
  20. }

创建前台Service

Service几乎都是在后台运行的,一直以来它都是默默地做着辛苦的工作。但是Service的系统优先级还是比较低的,当系统出现内存不足情况时,就有可能会回收掉正在后台运行的Service。如果你希望Service可以一直保持运行状态,而不会由于系统内存不足的原因导致被回收,就可以考虑使用前台Service。前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。当然有时候你也可能不仅仅是为了防止Service被回收才使用前台Service,有些项目由于特殊的需求会要求必须使用前台Service,比如说墨迹天气,它的Service在后台更新天气数据的同时,还会在系统状态栏一直显示当前天气的信息,如下图所示:

那么我们就来看一下如何才能创建一个前台Service吧,其实并不复杂,修改MyService中的代码,如下所示:

[java] view plaincopy
  1. public class MyService extends Service {
  2. public static final String TAG = "MyService";
  3. private MyBinder mBinder = new MyBinder();
  4. @Override
  5. public void onCreate() {
  6. super.onCreate();
  7. Notification notification = new Notification(R.drawable.ic_launcher,
  8. "有通知到来", System.currentTimeMillis());
  9. Intent notificationIntent = new Intent(this, MainActivity.class);
  10. PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
  11. notificationIntent, 0);
  12. notification.setLatestEventInfo(this, "这是通知的标题", "这是通知的内容",
  13. pendingIntent);
  14. startForeground(1, notification);
  15. Log.d(TAG, "onCreate() executed");
  16. }
  17. .........
  18. }

这里只是修改了MyService中onCreate()方法的代码。可以看到,我们首先创建了一个Notification对象,然后调用了它的setLatestEventInfo()方法来为通知初始化布局和数据,并在这里设置了点击通知后就打开MainActivity。然后调用startForeground()方法就可以让MyService变成一个前台Service,并会将通知的图片显示出来。

现在重新运行一下程序,并点击Start Service或Bind Service按钮,MyService就会以前台Service的模式启动了,并且在系统状态栏会弹出一个通栏图标,下拉状态栏后可以看到通知的详细内容,如下图所示。

Service和Thread的关系相关推荐

  1. Service 与 Thread 的区别

    Service 与 Thread 的区别 很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来 ...

  2. service和thread的区别,何时用service,何时用thread?

    按服务性质分local service和remote service 当它运行的时候如果是Local Service,那么对应的 Service是运行在主进程的 main 线程上的.如:onCreat ...

  3. 知识点干货--聊一聊Android中Service与Thread的区别

    古语说得好:"一寸光阴一寸金,寸金难买寸光阴."一寸光阴和一寸长的黄金一样昂贵,而一寸长的黄金却难以买到一寸光阴.比喻时间十分宝贵.此语句出自唐朝王贞白的<白鹿洞二首> ...

  4. Android 轮询最佳实践 Service + AlarmManager+Thread

    为什么80%的码农都做不了架构师?>>>    android中涉及到将服务器中数据变化信息通知用户一般有两种办法,推送和轮询. 消息推送是服务端主动发消息给客户端,因为第一时间知道 ...

  5. Android复习10【Service与Thread的区别、Service的生命周期、Service生命周期解析(相关方法详解、启动方式的不同、绑定)、音乐播放器+服务】

    音乐播放器Android代码下载:https://wws.lanzous.com/ifqzihaxvij 目   录 Service与Thread的区别 Service的生命周期 Service生命周 ...

  6. Activity、Service、Task、Process和Thread的关系

    Activity, Service,Task, Process and Thread之间到底是什么关系呢? 我们可以把TASK看成一个应用程式本身,当使用者点击应用程式以后,就启动了TASK,而TAS ...

  7. Android Service与Thread的区别

    Android Service,后台,Android的后台就是指,它的运行是完全不依赖UI的.即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行.比如说一些应用程序 ...

  8. 蓝牙知识【协议栈简图】 【 UUID解析 】 【属性、Characteris、描述符和Service以及profile的关系】【蓝牙无线通道】【INTER FRAME SPACE】【MTU】【缩写词】

    SYD8801是一款低功耗高性能蓝牙低功耗SOC,集成了高性能2.4GHz射频收发机.32位ARM Cortex-M0处理器.128kB Flash存储器.以及丰富的数字接口.SYD8801片上集成了 ...

  9. android Service中Thread.sleep不精确

    平台 RK3288 + Android 7.1 问题 在测试Thread.sleep过程中发现, 当App进入后台后, 服务中的Thread.sleep会有不同程度的精确度丢失. 测试sleep 2m ...

最新文章

  1. XSS攻击之窃取Cookie
  2. [转载] firefox与ie的javascript兼容性编程汇编
  3. 实战派mysql高阶应用指南_MySQL高阶SQL语句(学会这些,让你对于数据库游刃有余)_Gengchenchen的博客-CSDN博客...
  4. C++11学习笔记-----互斥量以及条件变量的使用
  5. 手机modem开发(15)---FT 测试天线注意事项
  6. 他的产品成华强北山寨模板,仅次华为苹果,这个赛道杀入年轻黑马!
  7. Android10 root,Android Q系统Magisk完美实现ROOT
  8. MongoDB安装配置(Windows)
  9. php1054,php – 找不到列:1054’字段列表’Laravel中的未知列’_token’
  10. 以index访问Tensor元素+ 反池化 unpool TensorFlow代码
  11. 8类网线利弊_CAT8 八类网线是何方神器?
  12. 记忆宫殿--清华一日游
  13. Ubuntu 安装 OpenFOAM + PETSc
  14. SPI都不知道?还敢说懂Dubbo?面试官怼的我哑口无言啊!!!
  15. 快速增加图片大小KB
  16. Lib之过?Java反序列化漏洞通用利用分析
  17. Java开发常用软件列表——持续更新
  18. vue的渐进式框架的理解
  19. 约瑟夫问题(丢手绢问题)
  20. 服务器电源系统,服务器电源系统于新一代数据中心设计的基础意义

热门文章

  1. hdu1007 最近点对
  2. 【C 语言】二级指针作为输入 ( 自定义二级指针内存 | 二级指针 排序 | 通过 交换指针方式 进行排序 )
  3. 【EventBus】EventBus 源码解析 ( 注册订阅者 | 注册订阅方法详细过程 )
  4. 【Android FFMPEG 开发】FFMPEG AVFrame 图像格式转换 YUV - RGBA ( 获取 SwsContext | 初始化图像数据存储内存 | 图像格式转换 )
  5. 2019年六月刷题列表
  6. react复习总结(1)--react组件开发基础
  7. LeetCode 26 Remove Duplicates from Sorted Array [Array/std::distance/std::unique] c++
  8. 在vue中给列表中的奇数行添加class
  9. TouTiao开源项目 分析笔记7 加载数据的过程
  10. java 基础 --静态