从Service到WorkManager
前言
关于Service,想必大家都太熟悉了,今天我们就再回顾下它的使用、概念、区别、变更历史等等。
概念和使用
Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件
两种启动方式:
startService() 生命周期为:onCreate() -> onStartCommand() -> onDestory() bindService() 生命周期为:onCreate() -> onBind() -> onUnBind() -> onDestory()其中要注意的是onStartCommand方法的返回值,有三种常量:
1) START_NOT_STICKY,终止服务后,除非除非有待传递的挂起 Intent,否则系统不会重建服务。
2) START_STICKY,终止服务后,会自动重新服务并调用 onStartCommand(),但不会重新传递最后一个 Intent。
3) START_REDELIVER_INTENT,终止服务后,会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand()。
当然,最后要使用的话还要在清单文件中注册:
<service android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:isolatedProcess=["true" | "false"] android:label="string resource" android:name="string" android:permission="string" android:process="string" > . . . </service>Service与子线程
关于Service,我的第一反应是运行在后台的服务。云服务器提供商
关于后台,我的第一反应又是子线程。
那么Service和子线程到底是什么关系呢?
Service有两个比较重要的元素:
长时间运行。Service可以在Activity被销毁,程序被关闭之后都可以继续运行。 不提供界面的应用组件。这其实解释了后台的意义,Service的后台指的是不和界面交互,不依赖UI元素。而且比较关键的点是,Service也是运行在主线程之中。
所以运行在后台的Service和运行在后台的线程区别还是挺大的。
首先,所运行的线程不同。Service还是运行在主线程,亿华云计算而子线程肯定是开辟了新的线程。 其次,后台的概念不同。Service的后台指的是不与界面交互,子线程的后台指的是异步运行。 最后,Service作为四大组件之一,控制它也更方便,只要有上下文就可以对其进行控制。当然,虽然两者概念不同,但是还是有很多合作之处。
Service作为后台运行的组件,其实很多时候也会被用来做耗时操作,那运行在主线程的Service肯定不能直接进行耗时操作,这就需要子线程了。
开启一个后台Service,然后在Service里面进行子线程操作,这样的结合给项目带来的b2b供应网可能性就更大了。
Google也是考虑到这一点,设计出了IntentService这种已经结合好的组件供我们使用。
IntentService
IntentService 是一个继承自Service,自带工作线程和Handler,并且线程任务结束后自动销毁的一个类。
源码很简单:
@Override public void onCreate() { super.onCreate(); //创建新线程并start HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); //创建新线程对应的handler mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { //service启动后发送消息给handler Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { //handler收到消息后调用onHandleIntent方法 onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } }弊端
之前也说了,Service这些特性确实给了我们更多的可能性,我们可以在后台静默下载项目需要的东西、可以发心跳包、可以处理一些数据。
但是,也正是因为后台无感知的特性,也带来了隐私方面的隐患和弊端。
App可以在后台操作用户数据,下载应用无关的文件等等。
所以Google为了保护用户隐私,在Android8.0开始,限制了后台Service。
后台和前台Service
这就涉及到Service的分类了。
如果从是否无感知来分类,Service可以分为前台和后台。前台Service会通过通知的方式让用户感知到,后台有这么一个玩意在运行。
比如音乐类APP,在后台播放音乐的同时,可以发现始终有一个通知显示在前台,让用户知道,后台有一个这么音乐相关的服务。
在Android8.0,Google要求如果程序在后台,那么就不能创建后台服务,已经开启的后台服务会在一定时间后被停止。
所以,建议使用前台Service,它拥有更高的优先级,不易被销毁。使用方法如下:
startForegroundService(intent); public void onCreate() { super.onCreate(); Notification notification = new Notification.Builder(this) .setChannelId(CHANNEL_ID) .setContentTitle("主服务")//标题 .setContentText("运行中...")//内容 .setSmallIcon(R.mipmap.ic_launcher) .build(); startForeground(1,notification); } <!--android 9.0上使用前台服务,需要添加权限--> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />