《第一行代码》第二版学习笔记(9)——服务

news/2024/12/22 9:07:22/

文章目录

  • 一、线程
  • 二、解决异步消息处理机制
    • 1、消息组成
    • 2、AsyncTask
  • 三、Service
    • 1、启动和停止服务
    • 2、活动和服务通信
    • 3、服务的生命周期
    • 4、创建前台服务
    • 5、使用IntentService
  • 四、服务的最佳实践

一、线程

android不允许在子线程中更新IU操作

二、解决异步消息处理机制

1、消息组成

  • Message:在线程之间传递消息
  • Handler:发送(SendMessage)和处理消息(handleMessage())
  • MessageQueue:存放所有通过Handler发送的消息
  • Looper:每个线程中MessageQueuede的管家,调用Looper的loop()方法后,就会进入到一个无线循环中,每当MessageQueue有消息时将它取出,传递到Handler的handleMessage()方法当中。

2、AsyncTask

AsyncTask是一个抽象类,子类继承AsyncTask时指定为3个泛型参数(也可以传void):

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

经常需要重写的方法

  • onPreExecute:后台任务开始执行调度之前,用于进行界面上的初始化操作。
  • doInBackground:这个方法中的所有代码都会在子线程中执行,在这处理所有耗时的任务。这个方法中不可以进行UI操作
  • onProgressUpdate:在这个方法中可以对UI进行操作
  • onPostExecute(Result):当后台任务执行完毕通过return语句返回时,这个方法很快就会被调用。执行一些任务的收尾工作。

三、Service

1、启动和停止服务

  • 定义服务
    在这里插入图片描述
if (v.getId() == R.id.start_service){Intent startIntent = new Intent(this,MyService.class);startService(startIntent);}else if (v.getId() == R.id.stop_service){Intent stopIntent = new Intent(this,MyService.class);stopService(stopIntent);}

2、活动和服务通信

比如希望在服务里提供一个下载文件的功能

  • 在服务中新建一个DownloadBinder类继承Binder,在这个类的内部提供一个下载和显示进度的方法。
 class DownloadBinder extends Binder{public void startDownload(){Log.d(TAG,"startDownload executed");}public int getProgress(){Log.d(TAG,"getProgress executed");return 0;}}
  • 在服务中创建这个类的实例,然后在onBind方法中返回这个实例
   @Overridepublic IBinder onBind(Intent intent) {// TODO: Return the communication channel to the service.//throw new UnsupportedOperationException("Not yet implemented");return mBinder;}
  • 在活动中创建ServiceConnection 匿名类,在类的onServiceConnected方法中通过向下转型得到了DownloadBinder的实例。
//    服务和活动绑定的解绑的时候用private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {downloadBinder = (MyService.DownloadBinder) service;downloadBinder.startDownload();downloadBinder.getProgress();}@Overridepublic void onServiceDisconnected(ComponentName name) {}};
  • 在活动中定义一个 ServiceConnection 对象和一个 boolean 变量用于跟踪服务是否已绑定, MyService.LocalBinder是服务中的类,可以通过这个类在活动中调用服务中的方法
private MyService myService;
private boolean isServiceBound = false;private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {MyService.LocalBinder binder = (MyService.LocalBinder) iBinder;myService = binder.getService();isServiceBound = true;}@Overridepublic void onServiceDisconnected(ComponentName componentName) {isServiceBound = false;}
};
  • 接下来,在活动的 onCreate() 方法中绑定服务:
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 创建意图以绑定服务Intent intent = new Intent(this, MyService.class);bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
  • 最后,在活动销毁时解绑服务:
@Override
protected void onDestroy() {super.onDestroy();if (isServiceBound) {unbindService(serviceConnection);isServiceBound = false;}
}

3、服务的生命周期

在Android中,服务(Service)是一种可以在后台执行长时间运行操作的组件,它没有用户界面。服务的生命周期包括以下几个关键方法:

  • onCreate():在服务被创建时调用。该方法只会被调用一次,用于进行一次性的初始化操作。
  • onStartCommand():在每次通过 startService() 方法启动服务时调用。该方法是服务的主要入口点,用于处理启动服务的请求,并执行相应的操作。它返回一个整数值,用于指定服务的行为,如何处理请求以及是否在服务被终止后重新启动。
  • onBind():在通过 bindService() 方法绑定服务时调用。该方法返回一个 IBinder 对象,用于提供与活动(或其他组件)进行通信的接口。如果服务不提供绑定功能,可以返回 null。
  • onUnbind():在通过 unbindService() 方法解绑服务时调用。该方法可以执行一些清理操作,如释放资源或取消相关的注册。如果返回 true,表示允许重新绑定该服务;如果返回 false,表示不允许重新绑定。
  • onDestroy():在服务被销毁时调用。该方法在服务即将被销毁时执行一些清理操作,释放资源等。在该方法执行后,服务将不再可用。

注:根据Android系统的机制,一个服务只要被启动或者绑定了之后,就会一直处于运行状态,必须要让两种条件同时不满足,服务才会被销毁。

4、创建前台服务

在 targetSdkVersion >= 34 的情况下,必须为应用内的每个前台服务(Foreground Service)指定至少一种前台服务类型。
使用时需要在 Manifest 文件中申请 android.permission.FOREGROUND_SERVICE 权限。service标签中的属性foregroundServiceType要和该权限对应。

   <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/><!-- android14前台常住服务权限--><uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"/><serviceandroid:name=".MyService"android:foregroundServiceType="specialUse"android:enabled="true"android:exported="true" />

在这里插入图片描述
让该服务变为一个前台服务:

 startForeground(1,notification);

5、使用IntentService

IntentService 让服务在子线程中运行

四、服务的最佳实践

报错:使用书籍提供的下载链接启动下载就失败,貌似是无权限访问,更换一个下载链接即可。


http://www.ppmy.cn/news/1455650.html

相关文章

PHP源码_众筹商城

众筹商城源码 众筹商品平台 商城加共识元富之路 网上商城众筹 前端是编译后的&#xff0c;后端PHP&#xff0c;带商城 运行截图 源码贡献 https://githubs.xyz/boot?app39 部分数据库表 CREATE TABLE ti_shopro_store (id int(11) NOT NULL AUTO_INCREMENT COMMENT ID,nam…

【C语言】数据类型

有哪些数据类型&#xff1f; char - 字符数据类型&#xff0c;存储一个字符&#xff0c;大小是1字节。short - 短整型&#xff0c;存储一个整数&#xff0c;大小是2字节。int - 整型&#xff0c;存储一个整数&#xff0c;大小是4字节。long - 长整型&#xff0c;存储一个整数&…

抖音开通蓝V前还有几百播放,开通后就没有流量了,原因在哪里?

作为抖音用户&#xff0c;你是否曾经认证过蓝V&#xff1f;你是否发现认证蓝V后&#xff0c;并没有增加更多的流量&#xff1f; 抖音认证蓝V是一种身份认证&#xff0c;是对内容创作者的一种肯定和认可。它代表了你的账号具备了一定的影响力和专业性&#xff0c;也能够给你带来…

快速入门!学习鸿蒙App开发的终极指南!

鸿蒙&#xff08;HarmonyOS&#xff09;是华为推出的一款分布式操作系统&#xff0c;旨在为不同设备提供统一的操作体验。鸿蒙App开发可以让应用程序在多个设备上实现流畅运行。本文将介绍鸿蒙App开发的终极指南&#xff0c;帮助您快速入门。 开发环境搭建 鸿蒙App开发过程需要…

leetcode 413.等差数列划分

思路&#xff1a;dp 因为正在练dp&#xff0c;所以这里就用dp的方法做了。 通过我们做过的一个题&#xff0c;就是leetcode 53.最大子段和那个&#xff0c;还有最长递增序列那一类题&#xff0c;我们可以知道&#xff0c;设置dp含义一般都是以什么什么数结尾&#xff0c;然后…

springboot项目组合定时器schedule注解实现定时任务

springboot项目组合定时器schedule注解实现定时任务&#xff01; 创建好springboot项目后&#xff0c;需要在启动类上增加注解开启定时器任务 下图所示&#xff1a; 增加这个注解&#xff0c;启动项目&#xff0c; package com.example.scheduledemo.util;import org.springf…

App在某个页面静止造成卡死假象

今天遇到一个bug记录下来,供后续积累经验。 预期结果:App在冷启动时会加载一个“广告页”,“广告页”有个定时器,定时器结束后会自动跳转到App首页;然而当用户开启指纹或人脸识别登录之后,App直接进入验证界面,验证通过后直接进入App首页。 bug场景:进入App需要指纹识别…

解决 java: 非法字符: ‘\ufeff‘

【报错解释】&#xff1a; 该错误通常发生在尝试编译Java源代码文件时&#xff0c;文件开头的字符是一个字节顺序标记&#xff08;Byte Order Mark&#xff0c;BOM&#xff09;&#xff0c;即\ufeff。在Java中&#xff0c;\ufeff不是一个合法的字符&#xff0c;因此编译器会报…