Android Service详解(一)

news/2024/7/7 13:10:20 标签: 移动开发, ui

Service系列一共2篇,主要介绍Service相关的使用,以及使用Service实现IPC通信。本文的重点是介绍Service相关的使用,通过Service 实现IPC通信放在下一篇讲解。

What is a Service

根据官方的介绍:

  1. Service既不是一个线程,Service通常运行在当成宿主进程的主线程中,所以在Service中进行一些耗时操作就需要在Service内部开启线程去操作,否则会引发ANR异常。
  2. 也不是一个单独的进程。除非在清单文件中声明时指定进程名,否则Service所在进程就是application所在进程。

Service存在的目的有2个:

  1. 告诉系统,当前程序需要在后台做一些处理。这意味着,Service可以不需要UI就在后台运行,不用管开启它的页面是否被销毁,只要进程还在就可以在后台运行。可以通过startService()方式调用,这里需要注意,除非Service手动调用stopService()或者Service内部主动调用了stopSelf(),否则Service一直运行。
  2. 程序通过Service对外开放某些操作。通过bindService()方式与Service调用,长期连接和交互,Service生命周期和其绑定的组件相关。

Service Lifecycle

public class MyService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return startCommandReturnId;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
复制代码

要解释这个首先要知道Service的实现,需要实现抽象方法onBind,以及重写onStartCommand,这2个方法会在下文介绍到。

通过上面的介绍可以知道,Service有3种启动方式:

  1. startService()
  2. bindService()
  3. 同时调用

这几种方式启动的Service生命周期略微不同。

startService方式

startService()只要一个Intent参数,指定要开启的Service即可

Intent intent = new Intent(MainActivity.this, MyService.class);
复制代码
  1. 当调用Service的startService()后,

    • Service首次启动,则先调用onCreate(),在调用onStartCommand()
    • Service已经启动,则直接调用onStartCommand()
  2. 当调用stopSelf()或者stopService()后,会执行onDestroy(),代表Service生命周期结束。

  3. startService方式启动Service不会调用到onBind()。 startService可以多次调用,每次调用都会执行onStartCommand()。 不管调用多少次startService,只需要调用一次stopService就结束。 如果startService后没有调用stopSelf或者stopService,则Service一直存活并运行在后台。

  4. onStartCommand的返回值一共有3种

    • START_STICKY = 1:service所在进程被kill之后,系统会保留service状态为开始状态。系统尝试重启service,当服务被再次启动,传递过来的intent可能为null,需要注意。
    • START_NOT_STICKY = 2:service所在进程被kill之后,系统不再重启服务
    • START_REDELIVER_INTENT = 3:系统自动重启service,并传递之前的intent

    默认返回START_STICKY;

bindService方式

通过bindService绑定Service相对startService方式要复杂一点。 由于bindService是异步执行的,所以需要额外构建一个ServiceConnection对象用与接收bindService的状态,同时还要指定bindService的类型。

//1. 定义用于通信的对象,在Service的onBind()中返回的对象。
public class MyBind extends Binder {
        public int mProcessId;
 }

//2. 定义用于接收状体的ServiceConnection
mServiceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //和服务绑定成功后,服务会回调该方法
                //服务异常中断后重启,也会重新调用改方法
                MyService.MyBind myBinder = (MyService.MyBind) service;
            }

            @Override
            public void onNullBinding(ComponentName name) {
                //Service的onBind()返回null时将会调用这个方法,并不会调用onServiceConnected()
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                // 当服务异常终止时会调用。
                // 注意,unbindService时不会调用
            }
        };
        
//3. 在需要的地方绑定到Service
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
复制代码

bindService()也可以调用多次,与startService()不同,当发起对象与Service已经成功绑定后,不会多次返回ServiceConnection中的回调方法。

通过bindService方式与Service进行绑定后,当没有对象与Service绑定后,Service生命周期结束,这个过程包括绑定对象被销毁,或者主动掉调用unbindService()

startService和bindService同时开启

当同时调用startService和bindService后,需要分别调用stopService和unbindService,Service才会走onDestroy()

一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

IntentService

通过上面的介绍我们知道,通过StartService形式开启Service时,如果不主动调用stopService,Service将在后台一直运行。同时如果我们在Service中执行耗时操作还是引起ANR异常,为了解决这2个问题,IntentService出现了。 当我们需要执行某些一次性、异步的操作时,IntentService能很好的满足这个场景。

IntentService相比于普通的Service,在使用时将不再需要实现onStartCommand(),同时需要实现onHandleIntent()。 真正需要我们处理的逻辑就在onHandleIntent()实现,IntentService会内部自动调用stopSelf()关闭自己。

至于防止ANR异常,具体的实现方式其实还是挺简单,就是在内部新建了子线程,并在子线程中内部的Looper来分发事件,具体代码就不贴了。

下一篇Android Service详解(二)将介绍通过Service实现IPC通信

转载于:https://juejin.im/post/5c6ff30b6fb9a049e5543ea4


http://www.niftyadmin.cn/n/834169.html

相关文章

【前端帮帮忙】第3期 使用CSS的border属性绘制各种几何形状

前言 border边框属性可以说是我们在网页布局中最常用不过的一个属性之一。border它不只是边框&#xff0c;它还有很多非常有用的“黑魔法”哈&#xff0c;让我们一起来学习一下。 border绘制几何形状的原理 我们先来看一个简单的小例子&#xff1a; 在页面上写一个div <div …

java软件测试工程师面试题_大公国际软件测试工程师面试题

大公国际软件测试工程师面试题时间&#xff1a;2014-12-04 10:53分享到&#xff1a;一、软件工程试题&#xff1a;(1)谈谈您对软件工程的理解。(2)您在以往的测试工作中都曾经具体从事过哪些工作?其中最擅长哪部分工作?(3)比较一下黑盒测试、白盒测试、单元测试、集成测试、系…

树形动态规划 java_树形动态规划

我颓了今天复习一下树形DP一道简单的入门树形DP代码如下#include#include#includeusing namespace std;const int maxn10007;int dp[maxn][2];bool f[maxn][2];int v[maxn];int cnt[maxn];int son[maxn][maxn];int fa[maxn];int work(int a,int b) //记忆化搜索{if(f[a][b]){re…

java httpsession_JavaWeb:HttpSession

环境JDK 8Spring Tool Suite 4.6.1Servlet 3.1Tomcat 8.5Maven 3.6.3HttpSession 说明HttpSession 总共有 17 个方法&#xff0c;其中 5 个方法已过期。Attribute 系列方法和 ServletContext、HttpServletRequest 类似&#xff0c;只不过作用域是整个会话。public Object getAt…

猜字游戏java_java程序,猜字游戏,希望大神帮忙

田心枫package com.may.eighteen;import java.util.Random;import java.util.Scanner;public class WeekDemo1 {public static void main(String[] args) {int number new Random().nextInt(200) 1;System.out.println("有一个数&#xff0c;在1-200之间。猜猜看&#x…

java vm文件_JavaVM执行的操作包括()。

案例分析一&#xff1a;假定CPU的主频是500MHz。硬盘采用DMA方式进行数据传送&#xff0c;其数据传输率为4MB/s, 每次DMA传输的数据量为8KB, 要求没有任何数据传输被错过。如果CPU在DMA初始化设置和启动硬盘操作等方面用了1000个时钟周期&#xff0c;并且在DMA传送完成后的中断…

华南理工深度学习与神经网络期末考试_深度学习不再是炼丹术!谷歌给出首个神经网络训练理论证明...

【新智元导读】谷歌 AI 最新发布的一篇论文给出了首个关于深度神经网络训练相关的理论证明&#xff0c;实验观察结果也为初步解释梯度下降强于贝叶斯优化奠定了基础。神经网络的理论面纱&#xff0c;正逐步被揭开。原来&#xff0c;神经网络实际上跟线性模型并没那么大不同&…

java应用程序异常_java – 系统异常与应用程序异常的清楚说明

当出现业务逻辑错误(而不是系统错误)时&#xff0c;应抛出应用程序异常。有一个重要的区别&#xff1a;应用程序异常不会自动导致事务回滚。客户端有机会在抛出应用程序异常后进行恢复。应用程序异常发送到客户端&#xff0c;而不会重新打包为EJBException。因此&#xff0c;您…