Service

Service简介

Service是Android程序中实现后台运行的解决方案,非常适合执行哪些不需要和用户交互而且还要求长期运行的任务。
特点:
1.Service不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序。
2.Service并不是运行在一个独立进程当中的,而是依赖于创建Service时所在的应用程序进程。当应用程序进程被杀掉时,所有依赖于该进程的Service也会3.Service并不会自动开启线程,所有的代码都是默认运行在主线程当中的。我们需要在Service内部手动创建子线程,并在这里执行具体的任务,否则有可能会出现线程阻塞的情况。

Android多线程编程

Android开启多线程和Java多线程一样,所以我们直接做知识迁移就可以了。

线程的基本用法

我们定义一个线程,

点击查看代码
class MyThread :Thread() {
	override fun run() {
		//编写业务逻辑
	}
}

启动一个线程只需要调用它的start方法就可以
MyThread.start()

2.我们还可以使用Runnbale接口来定义一个线程

点击查看代码
class MyThread: Runnable {
	override fun run() {
		//编写具体的逻辑
	}
}

启动线程
valmyThread= MyThread() Thread(myThread).start()

我们也可一使用Lambda表达:
Threa { //编写具体业务罗杰 }.start()
Kotlin中提供了一种更为简单的,这里的thread是衣蛾Kotlin内置顶层哈哈书,我们只需要在Lambda表达式中编写具体的逻辑就可以了。连start()方法都不用调用,thread函数在内部帮我处理好了
thread { //编写具体的逻辑 }

在子线程中更新UI

和许多GUI库一样,Android的UI也是线程不安全的,就是如果想更新应用程序里的UI元素,必须在主线程中进行,否则就会出现异常
我们新建一个AndroidThreadTest项目,然后修改activit_main中的代码:
image
然后再MainActivity里面编写代码:
image
当我们将项目运行起来进行更新的时候发现,这里程序出错,
原因就是在Android是不允许在子线程中进行UI操作,,但是我们有时候避免不了的子线程中更新相关的UI控件,这该怎么办呢?
Android中提供了一套异步消息的处理机制,完美解决了在子线程中进行UI操作的问题
修改MianActivity中的代码得知:
image
这种机制可以出色的解决在子线程中更新UI的问题

解析异步消息处理机制

我们来分析一下Android中异步消息机制到底是如何工作的?
Android中的异步消息处理机制主要有4部分组成,Message,Handler,MessageQueue和Looper
1.Message 是在线程之间传递的消息,它可以在内部携带少量信息,用于在不同线程之间传递数据。
2.Handler 用于发送和处理消息,发送消息一般是使用Handler的sendMessage,post方法。而发出的消息经过一系列地辗转处理后,最终会传递到Handle和handlMessage,
3.MessageQueue 是消息队列的意思,主要用于存放所有通过Handler发送的消息。这部分消息会一直存放在消息队列中,等待被处理。
4.Looper
每个线程中的MessageQueue的管家,调用Looper和loop()方法后,就会进入一个无线循环中,然后每当发现MessageQueue中存在一条消息时,就会将它取出,并传递到Handler和handleMessage()方法中,每个线程都会有Looper对象。

异步消息处理流程:
主线程中创建一个Handler对象,重写handlerMessage()方法
当子线程中需要进行UI操作的时候,就创建一个MessageQueue的队列中等待被处理,
Looper则会一直尝试从MessageQueue中取出消息去处理,最后分发回Handler的handleMessage()主方法中。
由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线程中运行
我们这样就可以安心进行UI操作。
image

使用AsyncTask

Android中也提供了另外一些好用的工具,让我们更加方便在子线程中对UI操作。AsyncTask背后实现的原理其实也是基于异步消息处理机制的,只是Android帮我们做了封装了

用法:由于AsyncTask是一个抽象类,我们想使用它就必须创建一个子类去继承它,在继承的时候AsyncTask为我们指定了3个泛型参数,这3个参数用途如下。
Params:在执行AsyncTask时需要传入的参数,可用于在后台中执行任务
Progress:需要在界面上显示当前进度,使用这里指定的泛型作为进度单位
Result:当任务执行完毕后,如果需要对结果进行返回,使用这里指定的泛型做为返回值

定义一个最简单的AsyncTask,
image

Service基本用法

定义一个Service

首先我们来看一下如何定义个一个Service,首先创建一个ServcieTest项目
我们创建一个Servcie
image
查看一下Service中的代码:
image

我们都知道四大组件的特点,就是需要在AndroidMainfest.xml中注册才能生效。
image

启动和停止Service

启动Service的方式是借助Intent来实现的,我们来使用代码实现
首先activit_mian布局文件中添加两个按钮,
image
编写MainACtivity中的代码:
image
我们再MainActivity中做日志输出
image
运行项目发现,
image
在Android 8.0系统开始应用后台的功能被大大削减

Activity和Service之间的通信

我们让Activity去指挥Service,这需要借助刚才的onBind方法了。
我们首先修改Myservice中的代码:
image
在activity_main布局文件中再添加两个按钮
image
然后编写MainActivity中的代码
image

image

启动程序之后,运行发现
执行了startDownload()和getProgress方法

Service生命周期

image

Service的更多技巧

介绍一些关于Service的高级技巧

使用前台Servcie

Service一旦进入应用后台,就面临着随时被回收的情况,如果你希望用户一直能够保持运行状态,就考虑使用前台Service,前台Service和普通Servce最大的区别就在于,前台有一个图标一直在系统状态栏显示,下拉状态栏后可以看到更多加详细的信息,非常了类似通知效果。
我们来编写代码实现:
image
在AndroidMainfest.xml中声明权限:
image

使用IntentServcie

Android提供了一个会自动停止,Service的机制,以保证我们程序的线程安全。IntentService,
image
在Activit中增加一个按钮,然后编写MainActivty中的代码:
image

最后需要砸AndroidMainfest代码中进行注册:
image

posted @   IT小五  阅读(697)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示