学习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.mzph.cn/news/743945.shtml

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

相关文章

Instant --java学习笔记

Instant 时间线上的某个时刻 / 时间戳过获取lnstant的对象可以拿到此刻的时间&#xff0c;该时间由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数不够1秒的纳秒数 Instant的常见方法&#xff1a; Instant可以用来记录代码的执行时间&#xff0c;或用于记录用户操作某…

面试经验分享 | 通关某公司面试靶场

0x00:探测IP 首先打开时候长这个样&#xff0c;一开始感觉是迷惑行为&#xff0c;试了试/admin&#xff0c;/login这些发现都没有 随后F12查看网络&#xff0c;看到几个js文件带有传参&#xff0c;就丢sqlmap跑了一下无果 随后也反查了域名一下&#xff0c;发现没有域名&#…

[java入门到精通] 20 反射精讲

复习 1.索引&#xff1a;主要是提高查询性能。 2.索引分类&#xff1a;主键索引 唯一索引 普通索引 组合索引 全文索引 hash索引 3.索引底层数据结构是btree.非叶子结点是由&#xff1a;索引指针域 叶子结点&#xff1a;索引数据(数据地址)&#xff0c;是双链表 4.jdbc:java…

《高效便捷,探索快递柜系统架构的智慧之路》

随着电商业务的蓬勃发展&#xff0c;快递柜系统作为一种高效、便捷的最后一公里配送解决方案&#xff0c;正在受到越来越多企业和消费者的青睐。本篇博客将深入探讨快递柜系统的架构设计理念、优势和实践&#xff0c;帮助读者了解如何构建智能化的快递柜系统&#xff0c;提升物…

简单的网页才好学习嘛!!!

做一个个人博客第一步该怎么做&#xff1f; 好多零基础的同学们不知道怎么迈出第一步。 那么&#xff0c;就找一个现成的模板学一学呗&#xff0c;毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题&#xff0c;那就是&#xff0c;那些模板都&#xff0c;太&#xff01;…

idea中操作Git将本地仓库代码完整提交到Gittee中

文章目录 1.在idea中打开你的项目根目录&#xff0c; idea中vcs -> create Git Repository2.选中你的项目所在的目录3. git commit -m"你的备注"4. 直接强制本地仓库覆盖远程仓库的东西5.或者直接使用git 进行这个操作 1.在idea中打开你的项目根目录&#xff0c; …

【Python/crawl】如何使用Python爬虫将一系列网页上的同类图片下载到本地

【需求】 从网页https://www.zhainq.com/%e7%be%8e%e5%a5%b3%e5%86%99%e7%9c%9f%e6%9c%ba%e6%9e%84/%e6%97%a5%e6%9c%ac%e7%be%8e%e5%a5%b3%e5%86%99%e7%9c%9f/109012.html 开始&#xff0c;有十七页&#xff0c;每页都有大漂亮“小濑田麻由”的若干图片&#xff0c;想要将其…

Gitee的注册和代码提交(附有下载链接)

目录 一、Git的下载和安装二、安装图形化界面工具三、在Gitee上创建仓库四、如何把仓库开源五、Clone远程仓库到本地六、拷贝代码到本地的仓库七、Add-Commit-Push到远程仓库八、可能出现的问题8.1 建议在本地仓库直接创建项目8.2 第一次Push可能出现的问题8.3 怎么删除Gitee上…

Element-Plus: Select组件实现滚动分页加载

Element-Plus的select组件并没有自带滚动分页加载的功能&#xff0c;其虽然提供了自定义下拉菜单的底部的方式可以自定义上一页及下一页操作按钮的方式进行分页加载切换&#xff1a; 但如果不想通过点击分页按钮的方式&#xff0c;利用滚动触底进行下一页加载的话&#xff0c;…

2024年太原等保测评中心名单看这里!

开年来&#xff0c;不少太原小伙伴打算做等保了。大家都在问&#xff0c;目前太原等保测评中心有哪些&#xff1f;在哪里丫&#xff1f;这不我们小编就给大家整理一下&#xff0c;仅供参考哈&#xff01; 2024年太原等保测评中心名单看这里&#xff01; 序号&#xff1a;1 …

[C++]20.实现红黑树。

实现红黑树 一.基本概念&#xff1a;1.红黑树的概念&#xff1a;2.红黑树的性质&#xff1a; 二.实现红黑树&#xff1a;1.基本结构&#xff1a;2.插入节点的多种情况&#xff1a;1.叔叔存在且为红&#xff1a;2.叔叔不存在/存在且为黑(单旋变色)3.叔叔不存在/存在且为黑(多旋&…

C/C++中{}的用法总结(全)

C基础专栏&#xff1a;http://t.csdnimg.cn/UjhPR 目录 1.定义初始化列表&#xff08;Initializer List&#xff09; 2.类成员初始化列表 3.无默认构造函数的类的默认初始化&#xff08;C11 及以后版本&#xff09; 4.初始化器列表构造函数&#xff08;C11 及以后版本&…

Docker学习之镜像管理(超详解析)

Docker镜像生命周期&#xff08;可以把docker镜像理解为虚拟机镜像&#xff09; 实验内容&#xff1a; 搜索官方仓库镜像 [rootlocalhost ~]# docker search busybox //以查找busybox为例 搜索说明&#xff1a;name镜像名称 description镜像说明 stars点赞数量 official…

四川宏博蓬达法律咨询有限公司:法律服务的行业翘楚

在当今社会&#xff0c;法律服务已经成为人们生活中不可或缺的一部分。随着法律意识的提高&#xff0c;选择一家专业、可靠的法律咨询公司显得尤为重要。四川宏博蓬达法律咨询有限公司&#xff0c;作为业内的佼佼者&#xff0c;以其卓越的服务质量和广泛的业务范围&#xff0c;…

Nacos 集群搭建

1 . 集群结构图 : 其中包括3个nacos结点&#xff0c;然后一个负载均衡器代理3个Nacos。这里负载均衡器可以使用nginx ; 我们计划的集群结构 : 三个nacos结点的地址 : 节点ipportnacos1192.168.150.18845nacos2192.168.150.18846nacos3192.168.150.18847 2 . 搭建集群 搭…

2024最新轻量应用服务器简介_轻量应用服务器购买指南

腾讯云轻量应用服务器开箱即用、运维简单的轻量级云服务器&#xff0c;CPU内存带宽配置高并且价格特别便宜&#xff0c;大带宽&#xff0c;但是限制月流量&#xff0c;轻量2核2G3M带宽61元一年、2核2G4M优惠价99元一年&#xff0c;540元三年、2核4G5M带宽165元一年&#xff0c;…

JAVA初阶数据结构(链表)练习(这些可以作为java包中的方法)

这里的每一个题大家都要仔细完成&#xff0c;这些题目每个我都至少思考了两个小时左右&#xff08;沉重心&#xff0c;慢慢来&#xff09; 1.反向链表的实现&#xff08;对链表进行翻转&#xff09;&#xff08;力扣有&#xff09; &#xff08;1&#xff09;图示 &#xff0…

2024考研国家线公布,各科分数线有哪些变化?考研国家线哪些涨了,哪些跌了?可视化分析告诉你

结论在文章结尾 2024考研国家线 一、近五年国家线趋势图-学术硕士 文学 管理学 工学照顾专业 体育学 交叉学科 军事学 历史学 理学 享受少数名族照顾政策的考生 中医类照顾专业 教育类 艺术类 医学 工学 哲学 法学 农学 经济学 二、近五年国家线趋势图-专业硕士 中医 应用心理 …

web项目的搭建

使用Webstorm并创建Next.js文件 1、配置nodejs环境、安装webstorm【配置node.js可以使用nvm去管理nodejs的版本】 2、需要破解webstorm&#xff0c;可能会导致原本的idea失效&#xff0c;注册码过期 3、taobao的npm过期&#xff0c;导致npm is sass执行不成功&#xff0c;需…

jvaweb 3-13

Element 后端开发 maven maven的作用 下载并配置环境变量 创建Maven项目 Maven坐标 依赖 Maven的依赖传递特性 以图表形式展示依赖 排除依赖 依赖范围 生命周期