展开说说:Android四大组件之Service使用

Service一定要开启子线程才可以执行耗时任务吗?不完全是吧。

Service是Android系统中的四大组件之一,它是一种没有可视化界面,运行于后台的一种服务程序属于计算型组件,用来在后台执行持续性的计算任务,重要性仅次于Activity活动。

本文分四块来记录,分别是普通Service、IntentService、ForegroundService,其中普通service根据运行状态不同分为startService启动的Service和bindService绑定的Service。

先定义一个Service子实现类,普通Service的启动的Service和bindService绑定的Service共用这一个Service类。

public class ServiceJia extends Service {private static final String TAG = ServiceJia.class.getName();@Nullable@Overridepublic IBinder onBind(Intent intent) {Log.e(TAG, "onBind: " );return new JiaBinder();}@Overridepublic void onCreate() {super.onCreate();Log.e(TAG, "onCreate: " );}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.e(TAG, "onStartCommand: " );new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(30000);Log.e(TAG, "onStartCommand:    等了半分钟" );} catch (InterruptedException e) {e.printStackTrace();}}}).start();Log.e(TAG, "onStartCommand:    -end" );return super.onStartCommand(intent, flags, startId);}//用于bindService时和activity交互public static class JiaBinder extends Binder {public void doSomething(String something){Log.e(TAG, "JiaBinder  --doSomething: "+something );}public void onClick(String something){Log.e(TAG, "JiaBinder  --onClick: "+something );}}}

1、startService启动Service和停止

通过startService()创建启动的service可以一直运行下去,必须自己调用stopSelf()方法或者其他组件调用stopService()方法来停止。适用于不和其他组件通讯的业务。

 //不可以阻塞线程做耗时操作,比如这样:

try {
     Thread.sleep(30000);
     } catch (InterruptedException e) {
           e.printStackTrace();
      }
 程序闪退报错:
2023-12-02 09:46:39.584 1592-1795/? E/ActivityManager: ANR in com.example.testdemo3 PID: 29467
Reason: executing service com.example.testdemo3/.service.ServiceJia
Load: 46.58 / 46.1 / 46.01
CPU usage from 70164ms to 0ms ago (2023-12-02 09:45:28.698 to 2023-12-02 09:46:38.862) with 99% awake:

启动和关闭服务:

startService.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {String text = startService.getText().toString();if ("startService".equals(text)){startService.setText("stopService");serviceIntent = new Intent(ServiceActivity.this, ServiceJia.class);startService(serviceIntent);}else if ("stopService".equals(text)){if (stopService(serviceIntent)){ //真停了再修改按钮的文字显示startService.setText("startService");}}}
});

2、bindService绑定Service和解绑

调用bindService()来创建,调用方可以通过一个IBinder接口和service进行通信,需要通过ServiceConnection建立连接多用于有交互的场景。

只能调用方通过unbindService()方法来断开连接。调用方可以和Service通讯,并且一个service可以同时和多个调用方存在绑定关系解除绑定也需要所有调用全部解除绑定之后系统会销毁service

绑定和解绑服务:

String text = bindService.getText().toString();
if ("bindService".equals(text)){
if (serviceIntent == null)serviceIntent = new Intent(ServiceActivity.this, ServiceJia.class);if (bindService(serviceIntent,serviceConnection, Context.BIND_AUTO_CREATE)){bindService.setText("unBindService");}
}else if ("unBindService".equals(text)){unbindService(serviceConnection);bindService.setText("bindService");
}

//连接成功,可以通过Binder调用绑定的service中的方法,比如jiaBinder.doSomething("start conncetion");

serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {Log.e(TAG, "onServiceConnected: " );jiaBinder = (ServiceJia.JiaBinder) iBinder;//连接成功,调用绑定的service中的方法jiaBinder.doSomething("start conncetion");}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.e(TAG, "onServiceDisconnected: " );}@Overridepublic void onBindingDied(ComponentName name) {Log.e(TAG, "onBindingDied: " );}@Overridepublic void onNullBinding(ComponentName name) {Log.e(TAG, "onNullBinding: " );}
};

3、IntentService

它可以解决第一句中“Service一定要开启子线程才可以执行耗时任务吗?”的问题。

IntentService 是 Android 中的一个服务,继承自 Service 类,并在单独的工作线程中执行任务,避免了多线程处理异步任务我们可以在onHandleIntent生命周期方法中执行耗时任务,不用开启子线程:

注意这里是继承IntentService

还有就是继承IntentService必须声明一个空参构造方法否则会报错删除 

public class MyIntentService extends IntentService {public static final String TAG = "MyIntentService";/*** Creates an IntentService.  Invoked by your subclass's constructor.* @param name Used to name the worker thread, important only for debugging.* 如果name字段为空,字符串就是worker thread的名字*/public MyIntentService(String name) {super(name);}public MyIntentService() {super(TAG);}/*** 可以做耗时任务* @param intent*/@Overrideprotected void onHandleIntent(@Nullable Intent intent) {String type = intent.getStringExtra("type");try {Log.e(TAG, "onHandleIntent:  -start" );Thread.sleep(10000);Log.e(TAG, "onHandleIntent:  -end" );} catch (InterruptedException e) {e.printStackTrace();}}

启动和关闭IntentService

intentService.setOnClickListener(new View.OnClickListener() {@RequiresApi(api = Build.VERSION_CODES.O)@Overridepublic void onClick(View v) {String text = intentService.getText().toString();if ("startIntentService".equals(text)){intentService.setText("stopIntentService");intentServiceIntent = new Intent(ServiceActivity.this, MyIntentService.class);startService(intentServiceIntent);}else if ("stopIntentService".equals(text)){boolean b = stopService(intentServiceIntent);Log.e(TAG, "onClick: stopIntentService= "+b );if (b){ //真停了再修改按钮的文字显示intentService.setText("startIntentService");}}}
});

这里有一个比较坑的地方就是,必须指定一个空参构造函数,否则运行就会报错。

4、前台服务

前台服务用于执行用户可察觉的操作。前台服务会显示状态栏通知,让用户知道当前应用正在前台执行任务并消耗系统资源。用户可以通过点击通知来与应用进行交互。

值得注意的两个点:

  • 除了在AndroidManifest.xml注册服务之外,还需要申请前台服务的权限,否则会闪退。

<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>

  • Build.VERSION_CODES.O及以上的系统,需要单独NotificationManager需要设置NotificationChannel否则会闪退,具体见下面代码。

闪退报错信息:“android.app.RemoteServiceException: Bad notification for startForeground

使用上和普通Service类似同样继承Service,但是要设置前台服务通知

startForeground(1000,notification);定义前台服务:
public class MyForegroundService extends Service {@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Notification.Builder builder = null;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {builder = new Notification.Builder(this,getChannelId("com.example.testdemo.service","MyForegroundService"));Notification notification = builder.setContentTitle("我是前台服务").setContentText("目前运行平稳").setSmallIcon(R.mipmap.ic_launcher).build();//设置前台服务startForeground(1000,notification);}else {//设置前台服务startForeground(1000,new Notification());}//被杀以后还会再次创建return START_STICKY;}@RequiresApi(api = Build.VERSION_CODES.O)private String getChannelId(String channelId, String channelName) {NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE);notificationChannel.setLightColor(Color.BLUE);notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);notificationManager.createNotificationChannel(notificationChannel);return channelId;}
}

启动和关闭前台服务:

 foregroundService.setOnClickListener(new View.OnClickListener() {@RequiresApi(api = Build.VERSION_CODES.O)@Overridepublic void onClick(View v) {String text = foregroundService.getText().toString();if ("startForegroundService".equals(text)){foregroundService.setText("stopForegroundService");foregroundServiceIntent = new Intent(ServiceActivity.this, MyForegroundService.class);
//                    startService(intentServiceIntent);startForegroundService(foregroundServiceIntent);}else if ("stopForegroundService".equals(text)){boolean b = stopService(foregroundServiceIntent);Log.e(TAG, "onClick: stopIntentService= "+b );if (b){ //真停了再修改按钮的文字显示foregroundService.setText("startForegroundService");}}}});

本文主要是记录了四种使用服务经常遇到的问题,后面再分析生命周期和源码。

才疏学浅,如有错误,欢迎指正,多谢。

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

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

相关文章

分子AI预测赛笔记

#AI夏令营 #Datawhale #夏令营 Taks1 跑通baseline 根据task1跑通baseline 注册账号 直接注册或登录百度账号&#xff0c;etc fork 项目 零基础入门 Ai 数据挖掘竞赛-速通 Baseline - 飞桨AI Studio星河社区 启动项目 选择运行环境&#xff0c;并点击确定&#xff0c;没…

台灯学生用哪个牌子最好?学生用台灯品牌排行榜分析

台灯学生用哪个牌子最好&#xff1f;护眼台灯在近年来成为家长和长时间使用电子设备人群关注的家电/学生产品。对于家中有孩子或经常面对电子屏幕的人士来说&#xff0c;很多人可能已经对这类产品有所了解并进行了购买。然而&#xff0c;部分家长对护眼台灯的认识还不够深入&am…

不同类型uORF对mORF翻译效率的影响

在您提供的文献《不同类型的uORF在真核生物基因表达中的调控潜力》中&#xff0c;对于不同类型的起始密码子的uORF及其对下游主开放阅读框&#xff08;mORF&#xff09;翻译效率的影响进行了详细的讨论。以下是这些影响的主要总结&#xff1a; uORF的起始密码子类型&#xff1a…

FFT 简单基础(matlab

使用 fs 进行采样&#xff0c;进行 N点FFT 选择显示0~N/21点的幅值 横坐标对应频率计算公式&#xff1a; fs * n / N 举个梨子&#xff1a; 频率2kHz采样1s&#xff0c;得到2000个点的序列y(n) 对序列y(n)做4096点的FFT 幅值响应对应的横坐标频率…

机器人控制系列教程之Stewart平台简介和运动学分析

Stewart平台简介及应用场景 六自由度 Stewart 并联机器人结构简图如下图所示&#xff0c;主要有一个固定平台和一个移动平台以及六个可伸缩的推杆组成&#xff0c;通常情况下&#xff0c;固定平台与底座连接&#xff0c;移动平台在空间具有六个自由度&#xff0c;通过六个推杆…

数据结构——求两个数的最大公因子

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> 数据结构——求两个数的最大公因子 要求&#xff1a;必须采用递归和非递归两种方法 非递归&#xff1a; int main() { int a 0; int b 0; scanf("%d %d", &a, &b); int c a…

攻防演练,怎么扫描一个网站

在 Ubuntu 22.04 上&#xff0c;你可以使用多种扫描工具来进行网站扫描。以下是一些常见的扫描工具以及它们的安装方法&#xff1a; Nmap: Nmap 是一个开源的网络扫描工具&#xff0c;用于发现网络和安全审计。安装命令&#xff1a;sudo apt update sudo apt install nmapNikto…

价格很实惠,希喂、爱立方、生生不息主食冻干抗得住实测吗?

在挑选主食冻干时&#xff0c;许多宠物主人都会感到头疼。尽管主食冻干相较于普通猫粮具有诸多优势&#xff0c;但其价格也相对高昂。这导致许多宠物主人担心高价购买的主食冻干可能营养价值并不理想。然而&#xff0c;在选择时&#xff0c;我们还需要考虑其他重要因素&#xf…

Spring MVC 中 使用 RESTFul 实现用户管理系统

1. Spring MVC 中 使用 RESTFul 实现用户管理系统 文章目录 1. Spring MVC 中 使用 RESTFul 实现用户管理系统2. 静态页面准备2.1 user.css2.2 user_index.html2.3 user_list.html2.4 user_add.html2.5 user_edit.html 3. SpringMVC环境搭建3.1 创建module&#xff1a;usermgt3…

tapd 与国内外主流的8大项目管理软件大对比

对比Tapd与8大项目管理工具&#xff1a;PingCode、Worktile、Redmine、Teambition、广联达、Jira、禅道、飞书。 Tapd 是腾讯推出的一款敏捷开发管理工具&#xff0c;特别适合那些需要高效协作和快速迭代的敏捷开发团队。它支持多种敏捷方法论&#xff0c;包括Scrum和Kanban&am…

《详细指南:本地部署Ollama大型模型的完整步骤》

《详细指南&#xff1a;本地部署Ollama大型模型的完整步骤》 引言 Ollama是一个高性能的AI模型部署平台&#xff0c;支持在本地轻松部署大型语言模型。本指南将详细介绍如何在本地环境中部署Ollama&#xff0c;并运行一个大型模型。 环境要求 操作系统&#xff1a;Windows/…

数学建模------Matlab数据可视化

目录 1.plot函数 &#xff08;1&#xff09;函数介绍 &#xff08;2&#xff09;参数介绍 &#xff08;3&#xff09;图形美化 &#xff08;4&#xff09;背景更改 &#xff08;5&#xff09;多组绘制 &#xff08;6&#xff09;图形叠加 &#xff08;7&#xff09;添加…

Elasticsearch备份数据到本地,并导入到新的服务 es 服务中

文章目录 使用elasticsearch-dump工具备份安装node.js(二进制安装)解压设置环境变量安装elasticsearch-dump docker安装使用ES备份文件到本地 使用elasticsearch-dump工具备份 这个工具备份时间比较长 安装node.js(二进制安装) wget https://nodejs.org/dist/v16.18.0/node-…

C语言 求分数序列的和

求分数序列2/1&#xff0c;3/2&#xff0c;5/3&#xff0c;8/5&#xff0c;13/8&#xff0c;21/13…。求出数列的n项和&#xff0c;n由键盘输入&#xff0c;并计算n20的结果 这个程序计算分数序列的前 n 项和&#xff0c;并输出 n 20 时的结果。 #include <stdio.h>in…

华为机试HJ13句子逆序

华为机试HJ13句子逆序 题目&#xff1a; 将一个英文语句以单词为单位逆序排放。例如“I am a boy”&#xff0c;逆序排放后为“boy a am I”所有单词之间用一个空格隔开&#xff0c;语句中除了英文字母外&#xff0c;不再包含其他字符 想法&#xff1a; 将输入的字符串通过…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 英文单词联想(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 https://app5938.acapp.acwing.com.cn/contest/2/problem/OD…

阿里云物联网应用层开发:第二部分,云产品流转

文章目录 哔哩哔哩视频教程1、云产品流转概述2、我们需要创建多少个云产品流转?3、阿里云物联网平台产品云流转实现3-1 创建数据源3-2 创建数据目的3-2 创建解析器,并关联数据、编写脚本哔哩哔哩视频教程 【阿里云物联网综合开发,STM32+ESP8266+微信小程序+web客户端一篇教程…

自定义控件动画篇(八)animateLayoutChanges与LayoutTransition的使用

在Android开发中&#xff0c;animateLayoutChanges 和 LayoutTransition 都是用来在布局改变时添加动画效果的特性&#xff0c;但是它们的使用场景和方式有所不同。 animateLayoutChanges animateLayoutChanges 是一个布尔属性&#xff0c;当它被设置为true时&#xff0c;会使…

jvm常见调优

FullGC的STW停顿时间长 单体应用一台硬件上的jvm的部署策略 单独的jvm管理堆内存 对于用户停顿时间敏感的系统&#xff0c;并不是必须使用Shenandoah或者ZGC这些明确以控制延迟为目标的垃圾回收器才能解决问题&#xff08;当然&#xff0c;这是最好的方法&#xff09;&#…

centos7安装宝塔面板

一、进入root模式 sudo su二、安装宝塔面板 if [ -f /usr/bin/curl ];then curl -sSO https://download.bt.cn/install/install_panel.sh;else wget -O install_panel.sh https://download.bt.cn/install/install_panel.sh;fi;bash install_panel.sh ed8484bec