Android | Service

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Android Service

Service 概念

实现程序后台运行的解决方案一种可在后台执行长时间运行操作而不提供界面的应用组件。Service 的运行不依赖于任何用户界面即使程序被切换到后台或者用户打开了另外一个应用程序Service 仍然能够保持正常运行。Service 并不是运行在一个独立的进程当中的而是依赖于创建 Service 时所在的应用程序进程。当某个应用程序进程被杀掉时所有依赖于该进程的 Service 也会停止运行。实际上 Service 并不会自动开启线程所有的代码都是默认运行在主线程当中的我们需要在 Service 的内部手动创建子线程并在这里执行具体的任务否则就有可能出现主线程被阻塞的情况。

Android 多线程

当需要执行一些耗时操作比如发起一条网络请求时考虑到网速等其他原因服务器未必能够立刻响应我们的请求如果不将这类操作放在子线程里运行就会导致主线程被阻塞从而影响用户对软件的正常使用。

Android多线程编程Java多线程编程 使用的语法大致相同当然也有些许区别。

Android 的UI是线程不安全如果想要更新应用程序里的 UI元素必须在主线程中进行否则就会出现异常。如果需要使用耗时的子线程的结果来更新相应的UI控件需要借助异步消息处理机制。

异步消息处理机制

Android 中的异步消息主要由四部分构成

  • Message在线程之间传递的消息它可以在内部携带少量的信息用于在不同线程之间传递数据。
  • Handler主要用于发送和处理消息的。发送消息一般是使用 HandlersendMessage() 方法、 post() 方法等而发出的消息经过一系列地辗转处理后最终会传递到 HandlerhandleMessage() 方法中。
  • MessageQueue主要用于存放所有通过 Handler 发送的消息。这部分消息会一直存在于消息队列中等待被处理。每个线程中只会有一个 MessageQueue 对象。
  • Looper每个线程中的 MessageQueue 的管家调用 Looperloop() 方法后就会进入一个无限循环当中然后每当发现 MessageQueue 中存在一条消息时就会将它取出并传递到 HandlerhandleMessage() 方法中。每个线程中只会有一个 Looper 对象。

异步消息的处理流程首先需要在主线程当中创建一个 Handler 对象并重写 handleMessage() 方法。然后当子线程中需要进行UI操作时就创建一个 Message 对象并通过 Handler 将这条消息发送出去。之后这条消息会被添加到 MessageQueue 的队列中等待被处理而 Looper 则会一直尝试从 MessageQueue 中取出待处理消息最后分发回 HandlerhandleMessage() 方法中。由于 Handler 的构造函数中我们传入了 Looper.getMainLooper()所以此时 handleMessage() 方法中的代码也会在主线程中运行然后便可以在此更新 UI。一条Message经过以上流程的辗转调用后也就从子线程进入了主线程从不能更新UI变成了可以更新UI。

AsyncTask

除了使用异步消息处理机制还可以借助 AsyncTask 工具。 AsyncTask 是对异步消息处理机制的一种封装。是一个抽象类必须创建一个子类去继承包含三个泛型参数

  • Params在执行AsyncTask时需要传入的参数可用于在后台任务中使用。
  • Progress在后台任务执行时如果需要在界面上显示当前的进度则使用这里指定的泛型作为进度单位。
  • Result当任务执行完毕后如果需要对结果进行返回则使用这里指定的泛型作为返回值类型。

需要重写的方法主要有以下几个

  • onPreExecute()这个方法会在后台任务开始执行之前调用用于进行一些界面上的初始化操作比如显示一个进度条对话框等。
  • doInBackground(Params...)这个方法中的所有代码都会在子线程中运行我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过 return语句 将任务的执行结果返回如果 AsyncTask 的第三个泛型参数指定的是 Unit 就可以不返回任务执行结果。注意在这个方法中是不可以进行UI操作的如果需要更新UI元素比如说反馈当前任务的执行进度可以调用 publishProgress (Progress...) 方法来完成。
  • onProgressUpdate(Progress...)当在后台任务中调用了 publishProgress(Progress...) 方法后onProgressUpdate (Progress...) 方法就会很快被调用该方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作利用参数中的数值就可以对界面元素进行相应的更新。
  • onPostExecute(Result)当后台任务执行完毕并通过 return语句 进行返回时这个方法就很快会被调用。返回的数据会作为参数传递到此方法中可以利用返回的数据进行一些UI操作比如说提醒任务执行的结果以及关闭进度条对话框等。

Service 生命周期

在这里插入图片描述

一旦在项目的任何位置调用了 ContextstartService() 方法相应的 Service 就会启动并回调 onStartCommand() 方法。如果这个 Service 之前还没有创建过 onCreate() 方法会先于 onStartCommand() 方法执行。 Service 启动了之后会一直保持运行状态直到 stopService()stopSelf() 方法被调用或者被系统回收。注意虽然每调用一次 startService() 方法 onStartCommand() 就会执行一次但实际上每个 Service 只会存在一个实例。所以不管你调用了多少次 startService() 方法只需调用一次 stopService()stopSelf() 方法Service 就会停止。

另外还可以调用 ContextbindService() 获取一个 Service 的持久连接这时就会回调 Service 中的 onBind() 方法。类似地如果这个 Service 之前还没有创建过onCreate() 方法会先于 onBind() 方法执行。之后调用方可以获取到 onBind() 方法里返回的 IBinder 对象的实例这样就能自由地和 Service 进行通信了。只要调用方和 Service 之间的连接没有断开Service 就会一直保持运行状态直到被系统回收。

当调用了 startService() 方法后再去调用 stopService() 方法。这时 Service 中的 onDestroy() 方法就会执行表示 Service 已经销毁了。类似地当调用了 bindService() 方法后再去调用 unbindService() 方法 onDestroy() 方法也会执行

Service 用法

每一个 Service 都需要在 AndroidManifest.xml 文件中进行注册才能生效。

可以通过将 Intent 传递给 startService()startForegroundService()Activity 或其他应用组件启动服务。Android 系统会调用服务的 onStartCommand() 方法并向其传递 Intent从而指定要启动的服务。

除非必须回收内存资源否则系统不会停止或销毁服务并且服务在 onStartCommand() 返回后仍会继续运行。服务必须通过调用 stopSelf() 自行停止运行或由另一个组件通过调用 stopService() 来停止它。

绑定服务允许应用组件通过调用 bindService() 与其绑定从而创建长期连接。此服务通常不允许组件通过调用 startService() 来启动它。如要创建绑定服务您需通过实现 onBind() 回调方法返回 IBinder从而定义与服务进行通信的接口。服务只用于与其绑定的应用组件因此若没有组件与该服务绑定则系统会销毁该服务。不必像通过 onStartCommand() 启动的服务那样以相同方式停止绑定服务。

  • 前台服务会有一个正在运行的图标在系统的状态栏显示下拉状态栏后可以看到更加详细的信息类似于通知的效果。即使用户停止与应用的交互前台服务仍会继续运行。视为处于前台的应用应当具有可见 Activity 或具有前台 Service 或另一个前台应用已关联到该应用。
  • 后台服务后台服务执行用户不会直接注意到的操作。Android 8.0 开始系统不允许后台应用创建后台 Service需要迁移方案去做处理。

Android 8.0 开始只有当应用保持在前台可见状态的情况下Service 才能保证稳定运行一旦应用进入后台之后Service 随时都有可能被系统回收。从 Android 9.0 系统开始使用 前台Service 必须在 AndroidManifest.xml 文件中进行权限声明。如果处于后台时应用需要创建一个前台 Service使用 startForegroundService() 方法而非 startService()

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: android