Android活动(activity)与服务(service)进行通信

文章目录

  • Android活动(activity)与服务(service)进行通信
    • 活动与服务进行通信
    • 服务的生命周期

Android活动(activity)与服务(service)进行通信

活动与服务进行通信

上一小节中我们学习了启动和停止服务的方法,不知道你有没有发现,虽然服务是在活动里启动的,但在启动了服务之后,活动与服务基本就没有什么关系了。确实如此,我们在活动里调用了startService()方法来启动MyService这个服务,然后MyService的onCreate()和onStartCommand()方法就会得到执行。之后服务会一直处于运行状态,但具体运行的是什么逻辑,活动就控制不了了。这就类似于活动通知了服务一下:“你可以启动了!”然后服务就去忙自己的事情了,但活动并不知道服务到底去做了什么事情,以及完成得如何。

那么有没有什么办法能让活动和服务的关系更紧密一些呢?例如在活动中指挥服务去干什么,服务就去干什么。当然可以,这就需要借助我们刚刚忽略的onBind()方法了。

比如说,目前我们希望在MyService里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度。实现这个功能的思路是创建一个专门的Binder对象来对下载功能进行管理,修改MyService中的代码,如下所示:

public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
...
}

可以看到,这里我们新建了一个DownloadBinder类,并让它继承自Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真正的功能,我们在这两个方法中分别打印了一行日志。

接着,在MyService中创建了DownloadBinder的实例,然后在onBind()方法里返回了这个实例,这样MyService中的工作就全部完成了。

下面就要看一看,在活动中如何去调用服务里的这些方法了。首先需要在布局文件里新增两个按钮,修改activity_main.xml中的代码,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<Button
android:id="@+id/bind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bind Service" />
<Button
android:id="@+id/unbind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Unbind Service" />
</LinearLayout>

这两个按钮分别是用于绑定服务和取消绑定服务的,那到底谁需要去和服务绑定呢?当然就是活动了。当一个活动和服务绑定了之后,就可以调用该服务里的Binder提供的方法了。修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
Button bindService = (Button) findViewById(R.id.bind_service);
Button unbindService = (Button) findViewById(R.id.unbind_service);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
...
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE); //绑定服务
break;
case R.id.unbind_service:
unbindService(connection); //解绑服务
break;
default:
break;
}
}
}

这里我们首先创建了一个ServiceConnection的匿名类,在里面重写了onServiceConnected()方法和onServiceDisconnected()方法,这两个方法分别会在活动与服务成功绑定以及活动与服务的连接断开的时候调用。在onServiceConnected()方法中,我们又通过向下转型得到了DownloadBinder的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。现在我们可以在活动中根据具体的场景来调用DownloadBinder中的任何public方法,即实现了指挥服务干什么服务就去干什么的功能。这里仍然只是做了个简单的测试,在onServiceConnected()方法中调用了DownloadBinder的startDownload()和getProgress()方法。

当然,现在活动和服务其实还没进行绑定呢,这个功能是在Bind Service按钮的点击事件里完成的。可以看到,这里我们仍然是构建出了一个Intent对象,然后调用bindService()方法将MainActivity和MyService进行绑定。bindService()方法接收3个参数,第一个参数就是刚刚构建出的Intent对象,第二个参数是前面创建出的ServiceConnection的实例,第三个参数则是一个标志位,这里传入BIND_AUTO_CREATE表示在活动和服务进行绑定后自动创建服务。

这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行。

然后如果我们想解除活动和服务之间的绑定该怎么办呢?调用一下unbindService()方法就可以了,这也是Unbind Service按钮的点击事件里实现的功能。

现在让我们重新运行一下程序吧,界面如图所示:

在这里插入图片描述

点击一下Bind Service按钮,然后观察logcat中的打印日志,如图所示:

在这里插入图片描述

可以看到,首先是MyService的onCreate()方法得到了执行,然后startDownload()和getProgress()方法都得到了执行,说明我们确实已经在活动里成功调用了服务里提供的方法了。

另外需要注意,任何一个服务在整个应用程序范围内都是通用的,即MyService不仅可以和MainActivity绑定,还可以和任何一个其他的活动进行绑定,而且在绑定完成后它们都可以获取到相同的DownloadBinder实例。

服务的生命周期

之前我们学习过了活动以及碎片的生命周期。类似地,服务也有自己的生命周期,前面我们使用到的onCreate()、onStartCommand()、onBind()和onDestroy()等方法都是在服务的生命周期内可能回调的方法。

一旦在项目的任何位置调用了Context的startService()方法,相应的服务就会启动起来,并回调onStartCommand()方法。如果这个服务之前还没有创建过,onCreate()方法会先于onStartCommand()方法执行。服务启动了之后会一直保持运行状态,直到stopService()或stopSelf()方法被调用。

注意,虽然每调用一次startService()方法,onStartCommand()就会执行一次,但实际上每个服务都只会存在一个实例。所以不管你调用了多少次startService()方法,只需调用一次stopService()或stopSelf()方法,服务就会停止下来了。

另外,还可以调用Context的bindService()来获取一个服务的持久连接,这时就会回调服务中的onBind()方法。类似地,如果这个服务之前还没有创建过,onCreate()方法会先于onBind()方法执行。之后,调用方可以获取到onBind()方法里返回的IBinder对象的实

例,这样就能自由地和服务进行通信了。只要调用方和服务之间的连接没有断开,服务就会一直保持运行状态。

当调用了startService()方法后,又去调用stopService()方法,这时服务中的onDestroy()方法就会执行,表示服务已经销毁了。类似地,当调用了bindService()方法后,又去调用unbindService()方法,onDestroy()方法也会执行,这两种情况都很好理解。

但是需要注意,我们是完全有可能对一个服务既调用了startService()方法,又调用了bindService()方法的,这种情况下该如何才能让服务销毁掉呢?根据Android系统的机制,一个服务只要被启动或者被绑定了之后,就会一直处于运行状态,必须要让以上两种条件同时不满足,服务才能被销毁。所以,这种情况下要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行。

这样你就已经把服务的生命周期完整地走了一遍。

如果对你有帮助,就一键三连呗(点赞+收藏+关注),我会持续更新更多干货~~

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

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

相关文章

基于FPGA的SD卡的数据读写实现(SD NAND FLASH)

文章目录 目录 1、存储芯片分类 2、NOR Flash 与 NAND Flash的区别 3、什么是SD卡&#xff1f; 4、什么是SD NAND&#xff1f; 5、SD NAND的控制时序 6、FPGA实现SD NAND读写 1、存储芯片分类 目前市面上的存储芯片&#xff0c;大致可以将其分为3大类&#xff1a; ① …

【回眸】QAC软件指南——错误分析篇(完整版)

前言 近期需要再次测一下代码&#xff0c;相比以前测试更有经验&#xff0c;也做了比较多的记录&#xff0c;正好将经验通过博客保留下来&#xff0c;为以后可能的QAC测试做准备。 安装导入分析代码 这部分在上一篇中已经详细介绍&#xff0c;具体请见&#xff0c;如有疑问可…

百元蓝牙耳机什么牌子的好?四大宝藏机型真实推荐,快速收藏!

作为一位蓝牙耳机爱好者&#xff0c;无论是上班、娱乐、学习我都离不开蓝牙耳机。通勤时候能听听音乐&#xff0c;是最好的享受&#xff0c;可以让我更加放松&#xff0c;尽情享受音乐带来的乐趣。但市面上的大多数蓝牙耳机都是货不对板的&#xff0c;不是音质一般、就是续航时…

谷歌发布 3 款 Gemini 新模型;字节开源 FLUX Dev Hyper SD Lora,8 步生图丨 RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

Seata执行原理分析-AT、XA、TCC、SAGA比较

分布式事务简介 1.1 本地事务 大多数场景下&#xff0c;我们的应用都只需要操作单一的数据库&#xff0c;这种情况下的事务称之为本地事务(Local Transaction)。本地事务的ACID特性是数据库直接提供支持。本地事务应用架构如下所示&#xff1a; 在JDBC编程中&#xff0c;我们…

priority_queue模拟

一、什么是priority_queue? priority_queue是C标准库中的一个容器适配器&#xff0c;用于实现优先队列&#xff08;priority queue&#xff09;的数据结构。优先队列是一种特殊的队列&#xff0c;其中的元素按照一定的优先级进行排序&#xff0c;每次取出的元素都是优先级最高…

从零开始掌握Vue实例

从零开始掌握Vue实例&#xff1a;深入理解数据绑定与生命周期的核心秘诀 引言 简要介绍主题&#xff1a; 在学习Vue.js的过程中&#xff0c;Vue实例是最基础也是最关键的部分。Vue实例是Vue应用的核心&#xff0c;它是数据、DOM元素和Vue组件之间的桥梁。掌握Vue实例的使用对于…

文件上传面板中限制需要的文件格式,并且隐藏“所有文件”选项

直接说需求&#xff1a;需要实现在文件上传面板中限制需要的文件格式&#xff0c;并且不想展示“所有文件”这个选项&#xff0c;应该怎么做嘞&#xff1f;效果如下图&#xff1a; 这里用到了 window.showOpenFilePicker 方法实现&#xff0c;首先定义接受的格式及限制&#xf…

格行“信号增强技术”引领行业创新,格行随身WiFi带你感受不一样的速度与激情,行业第一的随身WiFi并非浪得虚名!

近年来&#xff0c;随着市场保有量的不断提升与相关技术的不断扩展&#xff0c;我国随身WiFi市场已经到了发展质量更高的“2.0”阶段&#xff0c;消费者对随身WiFi的需求变得多元且“高级”。与之对应的供给端&#xff0c;品牌之间的竞争也从未停止&#xff0c;有的品牌选择卷价…

如何使用ssm实现实验室仪器设备管理系统

TOC ssm354实验室仪器设备管理系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化…

快来尝尝,食家巷荞面甜甜圈超赞

当荞面与甜甜圈相遇&#xff0c;便诞生了食家巷荞面甜甜圈&#xff0c;一种独具特色的美食体验。 食家巷荞面甜甜圈&#xff0c;外形圆润可爱&#xff0c;色泽金黄诱人。那精致的环状造型&#xff0c;仿佛是一个小小的魔法圈&#xff0c;散发着迷人的魅力。 与传统甜甜圈…

计算机网络面试真题总结(七)

文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 文章收录在网站&#xff1a;http://hardyfish.top/ 什么是对称加密、非对称加密&#xff1f; 对称加密是一种常用的加…

探索AI智能问答:改变未来交流的新动力

人工智能(AI)是当今科技领域中最具潜力和影响力的技术之一&#xff0c;AI智能问答系统更是这一领域中的一颗璀璨明珠。随着大数据和机器学习的发展&#xff0c;AI智能问答系统已经不仅仅是科幻小说中的幻想&#xff0c;而是正逐步融入我们的日常生活&#xff0c;从客户服务到教…

生成式AI扩散模型-Diffusion Model【李宏毅2023】概念讲解、原理剖析笔记

目录 一、Diffusion的基本概念和运作方法 1.Diffusion Model是如何运作的&#xff1f; 2.Denoise模块内部正在做的事情 如何训练Noise predictor&#xff1f; 1&#xff09;Forward Process (Diffusion Process) 2&#xff09;noise predictor 3.Text-to-Image 4.两个A…

入门Java第一步—>IDEA的下载与安装与JDK的环境配置(day01)

1.JDK的下载与安装 jdk的安装链接分为不同操作系统如下,点击链接跳转下载页面&#xff1a; windows操作系统JDK下载链接(按住键盘ctrl键单击链接即可)&#xff1a; 链接7天有效&#xff0c;有需要的评论区找我哈 通过网盘分享的文件&#xff1a;jdk-8u271-windows-x64.exe 链…

人工智能如何将人机交互提升到新水平

随着人工智能模型在语音识别和合成、文本处理和多模态性方面的卓越表现&#xff0c;终极语音用户界面可能很快就会无处不在。欢迎来到雲闪世界。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 那是一个典型的星期五下午&#xff0c;我们刚刚结束了一个…

如何用wireshark分析找出url接口和param参数???

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

Linux 内核源码分析---IPv6 数据包

IPv6是英文“Internet Protocol Version 6”&#xff08;互联网协议第6版&#xff09;的缩写&#xff0c;是互联网工程任务组&#xff08;IETF&#xff09;设计的用于替代IPv4的下一代IP协议&#xff0c;其地址数量号称可以为全世界的每一粒沙子编上一个地址。 由于IPv4最大的…

Tapd敏捷开发平台的使用心得

Tapd敏捷开发平台的使用心得 一、Tapd 简介 TAPD(Tencent Agile Product Development),腾讯敏捷产品研发平台行业领先的敏捷协作方案,贯穿敏捷产品研发生命周期的一站式服务,了解敏捷如下图 二、几个核心模块概念 需求迭代缺陷故事墙前期项目需求的管理,可以按类别建…

22AP10 SS524 平替 海思HI3521DV200 可提供开发资料

22AP10 是针对多路高清/超高清&#xff08;1080p/4M/5M/4K&#xff09;DVR 产品应用开发的新一代专 业 SoC 芯片。22AP10 集成了 ARM Cortex-A7 四核处理器和性能强大的图像分析工具 推理引擎&#xff0c;支持多种智能算法应用。同时&#xff0c;22AP10 还集成了多路 MIPI …