Android Service的解析

人不走空

🌈个人主页:人不走空****

💖系列专栏:算法专题****

**⏰诗词歌赋:**斯是陋室,惟吾德馨

Android服务,即Service,是Android四大组件之一,是一种程序后台运行的方案,用于不需要用户交互,长期运行的任务场景。

Service并不是在单独进程中运行,也是运行在应用程序进程的主线程中,在执行具体耗时任务过程中要手动开启子线程,应用程序进程被杀死,所有依赖该进程的服务也会停止运行。

由于ANR对Activity和BroadcastReceiver响应时间的限制(Activity对事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不适合执行较耗时操作,这样像网络、数据库、复杂计算这类耗时操作的执行就需要一个组件来承担。Service作为Android四大组件之一,其功能之一就是耗时操作的执行,主要功能如下:

  1. 执行需要长时间运行的操作,这个操作不与用户进行交互,如网络下载、大文件I/O、复杂计算。

  2. 应用内或应用间数据通信,Android每个应用程序都在自己的dalvik虚拟机中运行,一个应用是不允许访问其他应用的内存信息的,为此Android引入了Content Provider在不同应用间共享数据,BroadcastReceiver广播信息给不同应用程序,但Content Provider更多用于数据的共享,BroadcastReceiver广播的信息会被所有应用接收较耗费系统资源,对于两个应用间动态的进行交互还需要通过Service来完成。

Service的使用

Service的创建和Activity类似,也是通过Intent来实现的,既然是安卓四大组件之一,那么它也需要在清单文件中进行注册的。具体步骤如下。

Service的创建

新建一个TgsService继承自Service,并重写父类的onCreate()、onStartCommand()和onDestroy()方法,如下面的代码所示:

复制代码
public class TgsService extends Service {
    public static final String TAG = "TgsService";
    @Override    public void onCreate() {        super.onCreate();        Log.d(TAG, "onCreate");    }
    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.d(TAG, "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }
    @Override    public void onDestroy() {        super.onDestroy();        Log.d(TAG, "onDestroy");    }
    @Override    public IBinder onBind(Intent intent) {        return null;    }}

Service的注册

在清单文件中注册它,如下所示:

复制代码
<service android:name="com.tgs.demo.TgsService"            android:enabled="true"            android:exported="true"/>
  • enabled属性:是指该服务是否能够被实例化。如果设置为true,则能够被实例化,否则不能被实例化。默认值是true,一般情况下,我们都会需要实例化,所以也可以选择不设置。

  • exported属性:用于指示该服务是否能够被其他应用程序组件调用或跟它交互。如果设置为true,则能够被调用或交互(通常如果一个服务需要跨进程使用需要这么设置),设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。

Service的启动

接下来创建一个TgsActivity的测试活动,用于在其中创建TgsService对象,并在点击按钮时启动服务,示例代码如下:

复制代码
public class TgsActivity extends Activity implements View.OnClickListener {
    private Button startBtn;
    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_start);
        startBtn = (Button) findViewById(R.id.btn_start_service);
        startBtn.setOnClickListener(this);    }
    @Override    public void onClick(View v) {        if (v != null) {            switch (v.getId()) {                case R.id.btn_start_service:                    Intent startIntent = new Intent(this, TgsService.class);                    startService(startIntent);                    break;            }        }    }}

Service和Thread

如第一节所介绍的,Service是一个运行于后台的服务,一些比较耗时的操作也可以放在这里运行。而Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。这就会让人对这两个概念产生混淆了。

Service和Thread到底有什么关系呢?什么时候应该用Service,什么时候又应该用Thread?答案是:Service和Thread之间没有任何关系!前面有提到,Service其实是运行在主线程里的,因此它和Thread并没有关系。

Service与Thread的区别如下:

  1. Service是android的一种机制,当它运行的时候如果是Local Service,那么对应的Service是运行在主进程的main线程上的。如果是Remote Service,那么对应的Service则是运行在独立进程的main线程上。

  2. Thread是程序执行的最小单元,可以用Thread来执行一些异步的操作。

  3. 在应用中,如果是长时间的在后台运行,而且不需要交互的情况下,使用服务。同样是在后台运行,不需要交互的情况下,如果只是完成某个任务,之后就不需要运行,而且可能是多个任务,需要长时间运行的情况下使用线程。

  4. 如果任务占用CPU时间多,资源大的情况下,要使用线程。

那么如果用户既想使用Service的优点,又想使用Thread的优点,要怎么实现?关于这一点,Google已经帮我们想到了。即下节要介绍的IntentService。

IntentService

IntentService的概念

IntentService是Android中的一个系统封装类,继承自四大组件之一的Service,主要用于处理异步请求,实现多线程,它有以下特点:

  1. 是一种特殊的Service,继承自Service并且本身就是一个抽象类。

  2. 用于在后台执行耗时的异步任务,当任务完成后会自动停止。

  3. 有较高的优先级,不易被系统杀死(继承自Service的缘故),因此比较适合执行一些高优先级的异步任务。

  4. 内部通过HandlerThread和Handler实现异步操作。

  5. 创建IntentService时,只需实现onHandleIntent和构造方法,onHandleIntent为异步方法,可以执行耗时操作。

IntentService的创建

编写自己的Service类继承IntentService,并重写其中的onHandleIntent(Intent)方法,该方法是IntentService的一个抽象方法,用来处理我们通过startService方法开启的服务,传入参数Intent就是开启服务的Intent,如下所示:

复制代码
public class TgsIntentService extends IntentService {
    private static final String TAG = TgsIntentService.class.getSimpleName();
    public TgsService() {        super(TAG);    }
    @Override    protected void onHandleIntent(Intent intent) {        // 在这里添加我们要执行的异步代码    }}

IntentService的注册

接下来在AndroidManifest文件中的Application标签下添加刚刚创建的服务,如下所示:

复制代码
<service android:name="com.tgs.demo.TgsIntentService" />

IntentService的启动

然后创建一个TgsActivity的测试活动,并在点击按钮时调用startService系统函数来开启IntentService的服务,示例代码如下:

复制代码
public class TgsActivity extends Activity implements View.OnClickListener {
    private Button startIntentServiceBtn;
    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_start);
        startIntentServiceBtn = (Button) findViewById(R.id.btn_start_intent_service);
        startIntentServiceBtn.setOnClickListener(this);    }
    @Override    public void onClick(View v) {        if (v != null) {            switch (v.getId()) {                case R.id.btn_start_intent_service:                    Intent intent = new Intent(TgsActivity.this, TgsIntentService.class);                    startService(intent);                    break;            }        }    }}

Service的终止

一个已经启动了的Service必须管理它自己的生命期,系统不会停止或销毁这种Service,除非内存不够用了。Service在onStartCommand()返回后会继续运行。所以,service必须调用stopSelf()停止自己或由另一个组件调用stopService()来停止它。

一旦通过stopSelf()或stopService()发出了停止请求,系统就会尽可能快地销毁service。

关于Service的终止,需要注意以下几点:

  1. startService要stopSelf或者stopService才能终结。

  2. bindService要组件全部解绑后才会终结。

  3. 低内存的时候系统会主动停止和回收后台Service。

  4. 前台service很少被系统杀死,后台service随着时间推移变得更加可能被系统杀死。

  5. service被杀后会重启,但是取决于onStartCommand的返回值。

接下来创建一个TgsActivity的测试活动,用于在其中创建TgsService对象,并在点击按钮时停止服务,示例代码如下:​​​​​​​

复制代码
public class TgsActivity extends Activity implements View.OnClickListener {
    private Button stopBtn;
    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_start);
        stopBtn = (Button) findViewById(R.id.btn_stop_service);
        stopBtn.setOnClickListener(this);      }
    @Override    public void onClick(View v) {        if (v != null) {            switch (v.getId()) {                case R.id.btn_stop_service:                    Intent stopIntent = new Intent(this, TgsService.class);                    stopService(stopIntent);                    break;                      }        }    }}

参考链接

客户端27

Android开发12

客户端 · 目录

上一篇Android多线程的种类及使用方法下一篇Android组件之ContentProvider


作者其他作品:

【Java】Spring循环依赖:原因与解决方法

OpenAI Sora来了,视频生成领域的GPT-4时代来了

[Java·算法·简单] LeetCode 14. 最长公共前缀 详细解读

【Java】深入理解Java中的static关键字

[Java·算法·简单] LeetCode 28. 找出字a符串中第一个匹配项的下标 详细解读

了解 Java 中的 AtomicInteger 类

算法题 --- 整数转二进制,查找其中1的数量

深入理解MySQL事务特性:保证数据完整性与一致性

Java企业应用软件系统架构演变史​​​​​​​

相关推荐
踢球的打工仔1 天前
PHP面向对象(7)
android·开发语言·php
安卓理事人1 天前
安卓socket
android
安卓理事人1 天前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学1 天前
Android M3U8视频播放器
android·音视频
q***57741 天前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober1 天前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿1 天前
关于ObjectAnimator
android
zhangphil1 天前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我1 天前
从头写一个自己的app
android·前端·flutter
lichong9511 天前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端