这篇文章主要针对
Service
相关的知识点,进行详细的梳理,祝大家食用愉快!
文章目录
方便大家学习,我在 GitHub 建立了 仓库
-
仓库内容与博客同步更新。由于我在
稀土掘金
简书
CSDN
博客园
等站点,都有新内容发布。所以大家可以直接关注该仓库,以免错过精彩内容!
第一篇:Service 是什么
1.1 什么是 Service
Service
(服务) 是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。- 服务可由其他应用组件启动(如
Activity
),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity
)已销毁也不受影响。 - 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (
IPC
)。
1.2 Service 通常总是称之为 “后台服务”
- 其中 “后台” 一词是相对于前台而言的,具体是指:其本身的运行并不依赖于用户可视的
UI
界面 - 因此,从实际业务需求上来理解,
Service
的适用场景应该具备以下条件:
-
并不依赖于用户可视的
UI
界面(当然,这一条其实也不是绝对的,如前台Service
就是与Notification
界面结合使用的) -
具有较长时间的运行特性
-
注意: 是运行在主线程当中的
1.3 服务进程
-
服务进程是通过
startService()
方法启动的进程,但不属于前台进程和可见进程。例如,在后台播放音乐或者在后台下载就是服务进程。 -
系统保持它们运行,除非没有足够内存来保证所有的前台进程和可视进程。
第二篇:生命周期
2.1 Service 的生命周期
- 我们先来看看
Service
的生命周期 的基本流程 - 一张闻名遐迩的图
2.2 开启 Service 的两种方式
2.2.1 startService()
-
定义一个类继承
Service
-
在
Manifest.xml
文件中配置该Service
-
使用
Context
的startService(intent)
方法开启服务。 -
使用
Context
的stopService(intent)
方法关闭服务。 -
该启动方式,
app
杀死、Activity
销毁没有任何影响,服务不会停止销毁。
2.2.2 bindService()
-
创建
BindService
服务端,继承Service
并在类中,创建一个实现IBinder
接口的实例对象,并提供公共方法给客户端(Activity
)调用。 -
从
onBinder()
回调方法返回该Binder
实例。 -
在客户端(
Activity
)中, 从onServiceConnection()
回调方法参数中接收Binder
,通过Binder
对象即可访问Service
内部的数据。 -
在
manifests
中注册BindService
, 在客户端中调用bindService()
方法开启绑定Service
, 调用unbindService()
方法注销解绑Service
。 -
该启动方式依赖于客户端生命周期,当客户端
Activity
销毁时, 没有调用unbindService()
方法 ,Service
也会停止销毁。
2.3 Service 有哪些启动方法,有什么区别,怎样停用 Service
-
在
Service
的生命周期中,被回调的方法比Activity
少一些,只有onCreate
,onStart
,onDestroy
,onBind
和onUnbind
。 -
通常有两种方式启动一个
Service
, 他们对Service
生命周期的影响是不一样的。
2.3.1 通过 startService
Service
会经历onCreate
到onStart
,然后处于运行状态,stopService
的时候调用onDestroy
方法。
如果是调用者自己直接退出而没有调用
stopService
的话,Service
会一直在后台运行。
2.3.2 通过 bindService
Service
会运行 onCreate
,然后是调用 onBind
, 这个时候调用者和 Service
绑定在一起。调用者退出了,Srevice
就会调用 onUnbind
-> onDestroyed
方法。
所谓绑定在一起就共存亡了。调用者也可以通过调用
unbindService
方法来停止服务,这时候Srevice
就会调用onUnbind
->onDestroyed
方法。
2.3.3 需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢?
-
一个原则是
Service
的onCreate
的方法只会被调用一次,就是你无论多少次的startService
又bindService
,Service
只被创建一次。 -
如果先是
bind
了,那么start
的时候就直接运行Service
的onStart
方法,如果先是start
,那么bind
的时候就直接运行onBind
方法。 -
如果
service
运行期间调用了bindService
,这时候再调用stopService
的话,service
是不会调用onDestroy
方法的,service
就stop
不掉了,只能调用UnbindService
,service
就会被销毁 -
如果一个
service
通过startService
被start
之后,多次调用startService
的话,service
会多次调 用onStart
方法。多次调用stopService
的话,service
只会调用一次onDestroyed
方法。 -
如果一个
service
通过bindService
被start
之后,多次调用bindService
的话,service
只会调用一次onBind
方法。多次调用unbindService
的话会抛出异常。
第三篇:Service 与 Thread
3.1 Service 和 Thread 的区别
3.1.1 首先第一点定义上
thread
是程序执行的最小单元,他是分配cpu
的基本单位安卓系统中,我们常说的主线程,UI
线程,也是线程的一种。当然,线程里面还可以执行一些耗时的异步操作。- 而
service
大家记住,它是安卓中的一种特殊机制,service
是运行在主线程当中的,所以说它不能做耗时操作,它是由系统进程托管,其实service
也是一种轻量级的IPC
通信,因为activity
可以和service
绑定,可以和service
进行数据通信。 - 而且有一种情况,
activity
和service
是处于不同的进程当中,所以说它们之间的数据通信,要通过IPC
进程间通信的机制来进行操作。
3.1.2 第二点是在实际开发的过程当中
- 在安卓系统当中,线程一般指的是工作线程,就是后台线程,做一些耗时操作的线程,而主线程是一种特殊的线程,它只是负责处理一些
UI
线程的绘制,UI
线程里面绝对不能做耗时操作,这里是最基本最重要的一点。(这是Thread
在实际开发过程当中的应用) - 而
service
是安卓当中,四大组件之一,一般情况下也是运行在主线程当中,因此service
也是不可以做耗时操作的,否则系统会报 ANR 异常(ANR
全称:Application Not Responding
),就是程序无法做出响应。 - 如果一定要在
service
里面进行耗时操作,一定要记得开启单独的线程去做。
3.1.3 第三点是应用场景上
- 当你需要执行耗时的网络,或者这种文件数据的查询,以及其它阻塞
UI
线程的时候,都应该使用工作线程,也就是开启一个子线程的方式。 - 这样才能保证
UI
线程不被占用,而影响用户体验。 - 而
service
来说,我们经常需要长时间在后台运行,而且不需要进行交互的情况下才会使用到服务,比如说,我们在后台播放音乐,开启天气预报的统计,还有一些数据的统计等等。
3.2 为什么要用 Service 而不是 Thread
Thread
的运行是独立于Activity
的,也就是当一个Activity
被finish
之后,如果没有主动停止Thread
或者Thread
中的run
没有执行完毕时那么这个线程会一直执行下去。- 因此这里会出现一个问题:当
Activity
被finish
之后,你不再持有该Thread
的引用。 - 另一方面,你没有办法在不同的
Activity
中对同一Thread
进行控制。
3.3 Service 里面是否能执行耗时的操作
-
service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )
-
Service
不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service
中编写耗时的逻辑和操作(比如:网络请求,拷贝数据库,大文件),否则会引起ANR
。 -
如果想在服务中执行耗时的任务。有以下解决方案:
- 在
service
中开启一个子线程
new Thread(){}.start();
- 可以使用
IntentService
异步管理服务( 有关IntentService
的内容在后文中给出 )
3.4 Service 是否在 main thread 中执行
- 默认情况, 如果没有显示的指
service
所运行的进程,Service
和activity
是运 行在当前app
所在进程的main thread
(UI
主线程)里面。 Service
和Activity
在同一个线程,对于同一app
来说默认情况下是在同一个线程中的main Thread
(UI Thread
)- 特殊情况 ,可以在清单文件配置
service
执行所在的进程 ,让service
在另 外的进程中执行Service
不死之身
注:如果是在
application
里创建的Thread
:这个Thread
的生命周期就跟app
生命周期一致了,不同activity
也可操作它,这时service
和这个Thread
就很相似了(前提是这个service
只提供给自身app
使用,第三方app
不能访问)
3.4.1 在 onStartCommand
方法中将 flag
设置为 START_STICKY
;
return Service.START_STICKY;
3.4.2 在 xml 中设置了 android:priority
<service android:name=“.MyService”
android:priority=“2147483647”
3.4.3 在 onStartCommand
方法中设置为前台进程
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = new Notification(R.mipmap.ic_launcher, “服务正在运行”,System.currentTimeMillis());
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent,0);
RemoteViews remoteView = new RemoteViews(this.getPackageName(),R.layout.notification);
remoteView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
remoteView.setTextViewText(R.id.text , “Hello,this message is in a custom expanded view”);
notification.contentView = remoteView;
notification.contentIntent = pendingIntent;
startForeground(1, notification);
return Service.START_STICKY;
}
3.4.4 在 onDestroy
方法中重启 service
@Override
public void onDestroy() {
super.onDestroy();
startService(new Intent(this, MyService.class));
}
3.4.5 用 AlarmManager.setRepeating(…)
方法循环发送闹钟广播, 接收的时候调用 service
的 onstart
方法
Intent intent = new Intent(MainActivity.this,MyAlarmReciver.class);
PendingIntent sender = PendingIntent.getBroadcast( MainActivity.this, 0, intent, 0);
// We want the alarm to go off 10 seconds from now.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
//重复闹钟
/**
- @param type
- @param triggerAtMillis t 闹钟的第一次执行时间,以毫秒为单位
- go off, using the appropriate clock (depending on the alarm type).
- @param intervalMillis 表示两次闹钟执行的间隔时间,也是以毫秒为单位
- of the alarm.
- @param operation 绑定了闹钟的执行动作,比如发送一个广播、给出提示等等
*/
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 2 * 1000, sender);
3.4.6 目前市场面的很多三方的消息推送 SDK
唤醒 APP
, 例如 Jpush
PS
: 以上这些方法并不代表着你的Service
就永生不死了,只能说是提高了进程的优先级。迄今为止我没有发现能够通过常规方法达到流氓需求 (通过长按home
键清除都清除不掉) 的方法,目前所有方法都是指通过Android
的内存回收机制和普通的第三方内存清除等手段后仍然保持运行的方法,有些手机厂商把这些知名的app
放入了自己的白名单中,保证了进程不死来提高用户体验(如微信、app
一样躲避不了被杀的命运。
第四篇:IntentService
- 作为一个老司机,如果连
Interservice
都没听说过,那就有点那个啥了
4.1 什么是 IntentService
-
IntentService
是Service
的子类,比普通的Service
增加了额外的功能。 -
我们常用的
Service
存在两个问题:
-
Service
不会专门启动一条单独的进程,Service
与它所在应用位于同一个进程中 -
Service
也不是专门一条新线程,因此不应该在Service
中直接处理耗时的任务
4.2 IntentService 的特征
-
会创建独立的
worker
线程来处理所有的Intent
请求 -
会创建独立的
worker
线程来处理onHandleIntent()
方法实现的代码,无需处理多线程问题 -
所有请求处理完成后,
IntentService
会自动停止,无需调用stopSelf()
方法停止Service
-
为
Service
的onBind()
提供默认实现,返回null
-
为
Service
的onStartCommand
提供默认实现,将请求Intent
添加到队列中
4.3 Service 和 IntentService 区别
4.3.1 Service
是用于后台服务的
- 当应用程序被挂到后台的时候,为了保证应用某些组件仍然可以工作而引入了
Service
这个概念 - 那么这里面要强调的是:
Service
不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service
中编写耗时的逻辑和操作,否则会引起ANR
。
也就是,service 里面不可以进行耗时的操作。虽然在后台服务。但是也是在主线程里面。
4.3.2 当我们编写的耗时逻辑,不得不被 service
来管理的时候,就需要引入 IntentService
。
IntentService
是继承Service
的,那么它包含了Service
的全部特性,当然也包含service
的生命周期。- 那么与
service
不同的是,IntentService
在执行onCreate
操作的时候,内部开了一个线程,去你执行你的耗时操作。
4.3.3 使用:
- 重写
protected abstract void onHandleIntent(Intent intent)
4.3.4 IntentService
是一个通过 Context.startService(Intent)
启动可以处理异步请求的 Service
- 使用时你只需要继承
IntentService
和重写其中的onHandleIntent(Intent)
方法接收一个Intent
对象 , 在适当的时候会停止自己 ( 一般在工作完成的时候 ) 。 - 所有的请求的处理都在一个工作线程中完成 , 它们会交替执行 ( 但不会阻塞主线程的执行 ) ,一次只能执行一个请求。
4.3.5 是一个基于消息的服务
- 每次启动该服务并不是马上处理你的工作,而是首先会创建对应的
Looper
,Handler
并且在MessageQueue
中添加的附带客户Intent
的Message
对象。 - 当
Looper
发现有Message
的时候接着得到Intent
对象通过在onHandleIntent((Intent)msg.obj)
中调用你的处理程序,处理完后即会停止自己的服务。 - 意思是
Intent
的生命周期跟你的处理的任务是一致的,所以这个类用下载任务中非常好,下载任务结束后服务自身就会结束退出。
4.3.6 总结 IntentService
的特征有:
-
会创建独立的
worker
线程来处理所有的Intent
请求; -
会创建独立的
worker
线程来处理onHandleIntent()
方法实现的代码,无需处理多线程问题; -
所有请求处理完成后,
IntentService
会自动停止,无需调用stopSelf()
方法停止Service
;
第五篇:Service 与 Activity
5.1 Activity 怎么和 Service 绑定,怎么在 Activity 中启动对应的 Service
-
Activity
通过bindService(Intent service, ServiceConnection conn, int flags)
跟Service
进行绑定,当绑定成功的时候Service
会将代理对象通过回调的形式传给conn
,这样我们就拿到了Service
提供的服务代理对象。 -
在
Activity
中可以通过startService
和bindService
方法启动Service
。一般情况下如果想获取Service
的服务对象那么肯定需要通过bindService()
方法,比如音乐播放器,第三方支付等。 -
如果仅仅只是为了开启一个后台任务那么可以使用
startService()
方法。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/147d2d398e4fbdea31fb2cd05fd88266.jpeg)
总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
[外链图片转存中…(img-qeIEjZV8-1713057927419)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!