学习Android的第二十八天

目录

Android Service (服务)

线程

Service (服务)

Service 相关方法

Android 非绑定 Service

startService() 启动 Service

验证 startService() 启动 Service 的调用顺序

Android 绑定 Service

bindService() 启动 Service

验证 BindService 启动 Service 的顺序

startService() 启动 Service 后 bindService() 绑定

Android IntentService 耗时操作

IntentService

范例


Android Service (服务)

在 Android 中,Service 主要用于在后台执行长时间运行的操作,并且提供了与其他组件交互的机制。Service 和 Thread 有一些相似之处,但也存在着明显的区别。 Thread  在应用程序的进程内创建的轻量级执行单元。一个进程可以有多个线程,它们共享相同的内存空间和资源,是 Java 中用于实现并发的基本单位。

线程

我们先来看看 Thread (线程) 有关的一些概念:

  1. 程序(Program):指的是为了完成特定任务而用某种编程语言编写的一组指令集合,通常是静态的代码文件。
  2. 进程(Process):是操作系统中的一个独立执行单位,运行中的程序。每个进程都有独立的内存空间,操作系统为每个进程分配一段内存空间,用于存储程序的代码、数据以及运行时的状态信息。进程是操作系统进行资源分配和调度的基本单位,一个进程可以包含多个线程。
  3. 线程(Thread):是比进程更小的执行单元,是程序执行流的最小单元。一个进程中可以有多个线程,它们共享相同的内存空间和资源,但拥有各自的执行路径。线程由程序负责管理,而进程则由操作系统进行调度。
  4. 多线程的理解:多线程是指在一个程序中同时执行多个线程,每个线程都独立运行,并且可能同时访问共享的内存空间。虽然在单核处理器上实际上是分时执行的,但由于线程切换的速度非常快,用户会感觉到线程是同时执行的。
  5. 线程的生命周期:线程的生命周期包括创建、就绪、运行、阻塞和销毁等状态。线程的状态会随着执行过程中的不同操作而发生变化。

关于创建线程的方式,有三种常见的方法:

  • 继承 Thread 类:定义一个类继承自 Thread,并重写其 run() 方法来定义线程执行的任务。
  • 实现 Runnable 接口:定义一个类实现 Runnable 接口,并实现其 run() 方法,然后将该类的实例传递给 Thread 的构造方法。
  • 实现 Callable 接口:定义一个类实现 Callable 接口,并实现其 call() 方法,然后将该类的实例传递给 ExecutorService 的 submit() 方法。

在 Android 开发中,通常推荐使用第二种方式,即实现 Runnable 接口来创建线程。常见的做法是通过创建一个 Runnable 对象,并将其传递给 Thread 类的构造方法来创建新的线程。另外,也可以使用匿名类的方式来创建线程,这在 Android 开发中更为常见。

Service (服务)

在 Android 中,Service 是一种用于执行长时间运行操作的组件,可以在后台执行任务而不需要用户界面。Service 的生命周期包括以下方法:

1.onCreate():当 Service 第一次创建时调用。在此方法中,通常进行一次性的初始化操作,例如创建线程、初始化变量等。

2. onStartCommand(Intent, int, int):当通过 startService() 方法启动 Service 时调用。在此方法中,Service 可以处理启动请求并执行相应的操作。该方法会返回一个整数值,用于指示系统在 Service 终止后是否应该尝试重新启动该 Service。

3. onBind(Intent):当通过 bindService() 方法启动 Service 时调用。在此方法中,Service 返回一个 IBinder 对象,允许客户端与 Service 进行通信。如果不想允许绑定,则可以返回 null。

4. onUnbind(Intent):当所有客户端与 Service 解绑时调用。在此方法中,通常执行一些资源清理或其他必要的操作。

5. onDestroy():当 Service 即将销毁时调用。在此方法中,通常释放资源、停止线程等清理工作。

Android 中使用 Service 的方式有两种:

1. startService():通过调用 Context 的 startService() 方法来启动 Service。调用此方法后,Service 将会在后台运行,即使启动它的组件已经销毁。通常用于执行一次性任务,例如下载文件、播放音乐等。

2. bindService():通过调用 Context 的 bindService() 方法来绑定 Service。绑定 Service 后,客户端可以与 Service 进行通信,直到所有客户端解绑。通常用于需要与 Service 进行交互的场景,例如绑定到音乐播放器 Service 并控制播放状态。

这两种方式可以结合使用,例如通过 bindService() 方法绑定到 Service 并获取其实例,然后再调用其方法执行任务。

Service 相关方法

1、onCreate():

  • 说明:当 Service 第一次被创建后立即回调该方法。该方法在整个生命周期中只会调用一次。
  • 用途:通常在这个方法中进行一次性的初始化操作,比如创建线程、初始化变量等。

2、onDestroy():

  • 说明:当 Service 被关闭时会回调该方法。该方法只会在 Service 被销毁时调用一次。
  • 用途:通常在这个方法中执行一些清理工作,释放资源、停止线程等。

3、onStartCommand(intent, flag, startId)(在早期版本是 onStart(intent, startId)):

  • 说明:当客户端调用 startService(Intent) 方法时会回调。可多次调用 startService() 方法,但不会再创建新的 Service 对象,而是继续复用前面产生的 Service 对象,会继续回调onStartCommand() 方法。
  • 用途:用于处理客户端对 Service 的启动请求,执行相应的操作。方法的参数包括 Intent 对象(携带启动服务的请求信息)、flag(标志位)和 startId(启动命令的唯一标识)。

4、onBind(intent):

  • 说明:Service 必须实现的方法,该方法会返回一个 IBinder 对象,应用程序通过该对象与 Service 组件进行通信。
  • 用途:用于实现与客户端绑定的通信接口,返回的 IBinder 对象用于客户端与 Service 进行通信。

5、onUnbind(intent):

  • 说明:Service 上绑定的所有客户端都断开连接时会回调该方法。
  • 用途:通常在这个方法中执行一些资源清理或其他必要的操作。

Android 非绑定 Service

startService() 启动 Service

startService() 方法用于启动一个 Service。第一次启动 Service 时,会创建一个新的 Service 实例,并按顺序调用 onCreate() 和 onStartCommand() 方法。

一旦 Service 进入运行状态,再次调用 startService() 时,不会创建新的 Service 实例,而是系统会直接复用之前创建的 Service 实例,并调用其 onStartCommand() 方法。

这种 Service 与其调用者之间没有必然的联系,即使调用者的生命周期结束了,只要没有调用 stopService() 方法,Service 仍然会继续运行。

不论调用了多少次 startService(),只需调用一次 stopService() 就可以停止 Service 的运行。

验证 startService() 启动 Service 的调用顺序

1、MyService.java:

package com.example.myapplication2;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;public class MyService extends Service {private static final String TAG = "MyService";@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "onCreate()已调用");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "使用startId调用onStartCommand(): " + startId);return START_STICKY;}@Overridepublic IBinder onBind(Intent intent) {// 不是绑定式服务,返回 nullreturn null;}
}

2、MainActivity.java:

package com.example.myapplication2;import android.os.Bundle;
import android.content.Intent;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Log.d(TAG, "正在启动MyService。。。");Intent serviceIntent = new Intent(this, MyService.class);startService(serviceIntent);}
}

3、确保在 AndroidManifest.xml 文件中注册了 MyService:

<service android:name=".MyService"/>

4、运行效果如下

Android 绑定 Service

bindService() 启动 Service

bindService(Intent Service,ServiceConnection conn,int flags)

bindService() 方法是用于在 Android 应用程序中绑定服务的方法。下面是对参数的解释:

  • service:通过这个 Intent 参数指定要启动的服务。Intent 中包含了服务的标识符和其他必要的信息。
  • conn:ServiceConnection 对象,用于监听访问者与服务之间的连接情况。当连接成功时,会回调该对象中的 onServiceConnected(ComponentName, IBinder) 方法。当服务由于异常终止或其他原因与访问者断开连接时,会调用 onServiceDisconnected(ComponentName) 方法。需要注意的是,主动通过 unBindService() 方法断开连接并不会调用 onServiceDisconnected() 方法。
  • flags:指定绑定时是否自动创建服务。可以使用以下两个常量之一:0(不自动创建)或 BIND_AUTO_CREATE(自动创建)。如果服务还未创建且设置为自动创建,则在绑定时会自动创建服务。

通过调用 bindService() 方法,应用程序可以与服务建立连接,并通过 ServiceConnection 监听连接状态的变化。这样可以实现应用程序与服务之间的交互和通信。

注意:

  • 使用 bindService() 方法来启动服务,并通过参数传递要启动的服务以及一个 ServiceConnection 对象,用于监听连接情况。
  • 在 ServiceConnection 对象中,可以通过 onServiceConnected() 方法来处理与服务连接成功的情况,并在其中获取 IBinder 对象,以实现与服务之间的通信。
  • 如果服务所在的宿主异常终止或其他原因终止,会调用 onServiceDisconnected() 方法。
  • 解除与服务的绑定可以通过调用 unbindService() 方法来实现,此时会调用服务的 onUnbind() 和 onDestroy() 方法。
  • 多个客户端绑定同一个服务时,当所有客户端都解除绑定后,系统会销毁服务,除非服务也被 startService() 方法启动。
  • 在自定义服务中,一般需要继承 Binder 类并实现自己的 IBinder 对象,并在 onBind() 方法中返回该对象。

综上所述,通过绑定服务,应用程序能够与服务之间建立更为紧密的连接,并进行双向通信。

验证 BindService 启动 Service 的顺序

1、MainActivity.java:

package com.example.myapplication2;import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private TimerService timerService;private boolean isBound = false;private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {TimerService.TimerBinder binder = (TimerService.TimerBinder) service;timerService = binder.getService();isBound = true;Log.d(TAG, "onServiceConnected:TimerService已连接");}@Overridepublic void onServiceDisconnected(ComponentName name) {isBound = false;Log.d(TAG, "onServiceDisconnected:TimerService已断开连接");}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 启动并绑定服务Intent intent = new Intent(this, TimerService.class);bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {super.onDestroy();if (isBound) {unbindService(serviceConnection);isBound = false;}}
}

2、MyService.java:

package com.example.myapplication2;import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;public class TimerService extends Service {private static final String TAG = "TimerService";private final IBinder binder = new TimerBinder();private boolean isRunning = false;public class TimerBinder extends Binder {TimerService getService() {return TimerService.this;}}@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "onBind:TimerService绑定");return binder;}@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "onCreate:TimerService已创建");}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "StartCommand:TimerService已启动");return START_NOT_STICKY;}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy:TimerService已销毁");}// 启动计时器的方法public void startTimer() {Log.d(TAG, "StartTimer:计时器已启动");isRunning = true;}// 停止计时器的方法public void stopTimer() {Log.d(TAG, "stopTimer:计时器已停止");isRunning = false;}
}

3、确保在 AndroidManifest.xml 文件中注册了 TimerService:

<service android:name=".TimerService"/>

startService() 启动 Service 后 bindService() 绑定

当一个服务已经通过 startService() 方法启动后,即使有其他客户端通过 bindService() 方法绑定到该服务,服务仍然会保持运行状态,直到所有客户端都调用了 unbindService() 方法来解除绑定,并且没有其他客户端通过 startService() 方法启动了该服务,才会触发服务的销毁。

在这种情况下,如果调用 bindService() 来绑定到一个已经启动的服务,系统只是将服务的内部 IBinder 对象传递给客户端,不会将服务的生命周期与客户端绑定。因此,即使客户端调用 unbindService() 方法解除绑定,服务也不会被销毁。

总结起来,对于已经通过 startService() 启动的服务,即使有其他客户端通过 bindService() 方法绑定到该服务,服务也只有在所有客户端都调用了 unbindService() 方法解除绑定,并且没有其他客户端通过 startService() 方法启动了该服务时才会被销毁。

Android IntentService 耗时操作

IntentService

IntentService 是 Android 平台提供的一种服务,用于处理异步请求。它是 Service 类的一个子类,但相比普通的 Service,IntentService 更适合用来执行需要较长时间的操作,而且它可以在后台自动停止,无需手动控制。

下面是 IntentService 的一般用法:

  1. 启动 IntentService:客户端通过调用 startService(Intent) 方法来启动 IntentService。这个 Intent 包含了要执行的操作的描述。
  2. 自动停止:IntentService 在执行完所有的请求后会自动停止。这意味着我们不需要手动去停止 IntentService。
  3. 多次启动:IntentService 可以被启动多次。每次启动时,请求的 Intent 会被加入到工作队列中,然后按照队列顺序依次执行。注意,虽然可以多次启动 IntentService,但是每次只会执行一个工作线程,确保操作的顺序性和线程安全性。
  4. onHandleIntent() 回调方法:每个请求的操作会在 IntentService 的 onHandleIntent(Intent) 回调方法中执行。这个方法在工作线程中执行,因此可以执行耗时操作,而不会阻塞主线程。

通过这些特性,IntentService 提供了一种方便的方式来处理异步操作,尤其适合那些需要按顺序执行的任务或者需要在后台执行的长时间操作。

范例

1、MyIntentService.java

package com.example.myapplication2;import android.app.IntentService;
import android.content.Intent;
import android.util.Log;public class MyIntentService extends IntentService {private static final String TAG = "MyIntentService";public MyIntentService() {super("MyIntentService");}@Overrideprotected void onHandleIntent(Intent intent) {// 打印一些日志for (int i = 0; i < 5; i++) {Log.d(TAG, "正在执行任务 " + i);try {// 模拟耗时操作Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}// 任务完成后,IntentService 会自动停止}
}

2、确保在 AndroidManifest.xml 文件中注册了 MyIntentService:

<serviceandroid:name=".MyIntentService"android:exported="false" />

3、接下来,在应用中启动这个 IntentService:

package com.example.myapplication2;import android.content.Intent;
import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, MyIntentService.class);startService(intent);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/276839.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI】如何创建自己的自定义ChatGPT

如何创建自己的自定义ChatGPT 目录 如何创建自己的自定义ChatGPT大型语言模型(LLM)GPT模型ChatGPTOpenAI APILlamaIndexLangChain参考推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课本文将记录如何使用OpenAI GPT-3.5模型、LlamaIndex和LangChain创建自己的…

DirectShowPlayerService::doSetUrlSource: Unresolved error code 0x800c000d

报出这个问题&#xff0c;应该是对给的url解析不正确&#xff0c;我给的是rtsp的视频流地址&#xff0c;应该是对该格式解析异常。 所以参考两篇文&#xff1a; QT无法播放视频&#xff1a;报错&#xff1a;DirectShowPlayerService::doRender: Unresolved error code 0x8004…

vue3项目随笔1

1,Eslint Prettier 报错情况&#xff1a; 解决办法&#xff1a; &#xff08;1&#xff09;下载Prettier - code formatter &#xff08;2&#xff09;配置setting.json文件 文件 -> 首选项 -> 设置 -> 用户 -> Eslint "editor.defaultFormatter":…

拖动排序与置顶的Java实现

文章目录 1、需求分析2、表设计3、接口设计4、业务层5、数据层 整理个需求的实现思路。 1、需求分析 列表展示了一系列产品&#xff0c;现要支持通过拖动来给产品排序&#xff0c;也要支持单个产品的置顶、删除。类似CSDN的专栏文章管理。 2、表设计 现要支持对列表的产品进…

融入Facebook的世界:探索数字化社交的魅力

融入Facebook的世界&#xff0c;是一场数字化社交的奇妙之旅。在这个广袤的虚拟社交空间中&#xff0c;人们可以尽情展现自己、分享生活&#xff0c;与全球朋友、家人和同事保持紧密联系&#xff0c;共同探索社交互动的乐趣与魅力。让我们深入了解这个世界的魅力所在&#xff1…

ASP.NET-Server.HtmlEncode

目录 背景: 1.转义特殊字符&#xff1a; 2.防止跨站脚本攻击&#xff08;XSS&#xff09;&#xff1a; 3.确保输出安全性&#xff1a; 4.保留原始文本形式&#xff1a; 5.与用户输入交互安全&#xff1a; 实例说明: 不用Server.HtmlEncode 效果展示: 用Server.HtmlEnc…

多场成像,快速提高机器视觉检测能力--51camera

多阵列CMOS传感器与芯片级涂层二向色滤光片相结合&#xff0c;可在单次扫描中同时捕获明场、暗场和背光图像。 多场成像是一种新的成像技术&#xff0c;它可以在不同的光照条件下同时捕获多幅图像。再加上时间延迟积分(TDI)&#xff0c;这种新兴的成像技术可以克服许多限制的传…

【敬伟ps教程】视频动画

文章目录 视频文档视频时间轴帧动画视频文档 工作区需由[基本功能]切换为[动感] 可以看到我们需从时间的维度来编辑动态视觉图像 时间轴:从时间的维度来编辑动态视觉图像 PS提供的时间轴有两种:1、视频时间轴;2、动画时间轴 新建视频文档,点击新建或Ctrl+N,预设选择“胶…

springboot276基于JS的个人云盘管理系统的设计与实现

个人云盘管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装个人云盘管理系统软件来发挥其…

3.自定义工程目录配置CMakeLists

问题背景 熟悉stm32keil开发的都知道&#xff0c;我们在编写不同的外设时&#xff0c;通常都会单独编写一个app文件夹或者是user文件夹之类的来存放不同外设功能的源文件和头文件。 在前面一节2.构建第一个工程并烧录到ESP32开发板-CSDN博客中&#xff0c;我们是使用了一个乐鑫…

【联邦学习贡献评估-参与方贡献评估方案的介绍】

在明确如何度量参与方组合数据价值的基础上, 本篇介绍如何进一步度量参与方在联邦合作中的贡献, 具体介绍如下 4 种参与方贡献评估方案. 个体法 将参与方自身数据的价值度量或者相关变体作为该参与方的贡献. 个体法可以基于任何 数据价值度量指标进行, 特别地, 有个体信誉、个…

Python面试笔记

Python面试笔记 PythonQ. Python中可变数据类型与不可变数据类型&#xff0c;浅拷贝与深拷贝详解Q. 解释什么是lambda函数&#xff1f;它有什么好处&#xff1f;Q. 什么是装饰器&#xff1f;Q. 什么是Python的垃圾回收机制&#xff1f;Q. Python内置函数dir的用法&#xff1f;Q…

SpringBoot整合Activiti7——实战之请假流程(普通)

文章目录 代码实现xml文件部署流程启动流程查询任务填写请假单部门审批 请假流程&#xff1a;开始-填写请假单-部门审批-结束 代码实现 xml文件 <?xml version"1.0" encoding"UTF-8"?> <definitions xmlns"http://www.omg.org/spec/BPMN/…

服务器段的连接端口和监听端口编程实现

new ServerSocket(int)是开启监听端口&#xff0c;并不是连接端口。真正的连接端口是随机开辟的空闲端口&#xff0c;当连接创建完成后&#xff0c;监听关口可以继续等待下一次连接请求&#xff0c;处于空闲等待状态。 编程实现方式 1 、主线程一直处于阻塞等待状态&#xff0c…

编程高级陷阱-破坏原有生态

今天聊点有意思的&#xff0c;昨天写了一个链表翻转&#xff0c;说一说里面大家会遇到的坑&#xff0c;具体可以看 教你三指针拿捏链表翻转-CSDN博客 有这样一个场景&#xff0c;给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回…

汇总全网免费API,持续更新(新闻api、每日一言api、音乐。。。)

Public&FreeAPI 网址&#xff1a;apis.whyta.cn &#xff08;推荐&#xff09; UomgAPI 网址&#xff1a;https://api.uomg.com 教书先生 网址&#xff1a;https://api.oioweb.cn/ 山海API https://api.shserve.cn/ 云析API铺 https://api.a20safe.com/ 韩小韩…

提交数据加快百度搜索引擎收录

百度站长工具做了更新&#xff0c;百度收录的地址分享如下&#xff0c;新站点提交后&#xff0c;可以加快百度收录。 普通收录_加快网站内容抓取&#xff0c;快速提交数据工具_站长工具_网站支持_百度搜索资源平台普通收录工具可实时向百度推送数据&#xff0c;创建并提交site…

【Git】Github 上commit后,绿格子contribution却不显示?不知道怎么弥补?解决方法在这里

github 上commit后&#xff0c;绿格子&#xff08;contribution&#xff09;却不显示 问题描述 今天一直在github上面commit代码&#xff0c;但是github中并没有显示自己的contribution&#xff08;没有绿色的格子&#xff09;&#xff0c;全是空白&#xff0c;网上一查是因为…

tcp/ip协议2实现的插图,数据结构8 (30 - 32章)

(201) 201 三十0 中断优先级补充 (202) 202 三十1 TCP的用户需求 函tcp_usrreq一 (203) 203 三十2 TCP的用户需求 函tcp_usrreq二 (204) 204 三十3 TCP的用户需求 函tcp_usrreq三 (205) 205 三十4 TCP的用户需求 函tcp_usrreq四 (206) 206 三十5 TCP的用户需求 函tcp_usrreq五 …

Python爬虫:原理与实战

引言 在当今的信息时代&#xff0c;互联网上的数据如同浩瀚的海洋&#xff0c;充满了无尽的宝藏。Python爬虫作为一种高效的数据抓取工具&#xff0c;能够帮助我们轻松地获取这些数据&#xff0c;并进行后续的分析和处理。本文将深入探讨Python爬虫的原理&#xff0c;并结合实战…