• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Android笔记六Service概述

武飞扬头像
Frms
帮助1

安卓多线程操作

Handle简单用法

// 在主线程中,定义之
private val handler = object : Handler(Looper.getMainLooper()) {
		override fun handleMessage(msg: Message)
		{
			// 更新主线程
			textView.text = msg.what.toString()
		}
	}
	
	// 这里用于模拟延时的操作
	private fun runThread()
	{
		thread {
			// 线程休眠,模拟数据计算
			Thread.sleep(5000)
			
			val msg = Message()
			msg.what = 10086   (random()*1000).toInt()
			// 发送数据
			handler.sendMessage(msg)
		}
	}
学新通

Handle 异步消息处理机制

主要由四个部分构成:MessageHandlerMessageQueueLooper

  1. Message
    在线程传递消息,可以用what传递一个Int,也可用arg1arg2携带一些整型数据,使用obj字段携带一个Object对象
  2. Handler
    发送和处理消息。发送一般用sendMessgae()post()方法等,发出的消息最终会传递到handleMessage()中。
  3. MessageQueue
    消息队列,主要存放所有Handle发出的消息,这些消息会一直存在,等待处理,每个线程只有一个此对象。
  4. Looper
    是每个MessageQueue的管家,调用Looper.loop()就会进入循环,直到发现MessageQueue存在一条消息时,就会将他取出,传递给Handle的handleMessage(),每个线程只有一个此对象。

基本思想

 Handle发送消息给MessageQueue,Looper循环取出消息处理,处理结束后发回。

其他多线程概述

AsyncTask 在 Android 11正式弃用,不再论述
Coroutines - Kotlin 协程,篇幅大,后面在详细说
其他 - 不再概述

Service基本用法

创建一个Service

这里可以使用模板创建:
学新通
选项内的Exported指的是是否将服务暴露给外部访问,而Enabled则是否启用这个服务。
这是部分创建和重写的代码:

class MyService : Service()
{

	override fun onBind(intent: Intent): IBinder
	{
		TODO("Not yet implemented")
	}

	// 创建时调用
	override fun onCreate()
	{
		super.onCreate()
	}

	// 每次启动时调用
	override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int
	{
		return super.onStartCommand(intent, flags, startId)
	}

	//销毁时调用,用于回收资源
	override fun onDestroy()
	{
		super.onDestroy()
	}
}
学新通

值得注意的是,作为四大组件之一的服务,他也需要在AndroidManifest添加申明。但模板已经给我们加好了:

<service
      android:name=".MyService"
      android:enabled="true"
      android:exported="true">
</service>

启用和停止服务

// 启用
startService(Intent(this@MainActivity, MyService::class.java))
// 停止
stopService(Intent(this@MainActivity, MyService::class.java))

另外,服务也可以自我停止,在内部调用stopSelf()即可。

注意点

在Android8.0开始,只有应用保持在前台,才能稳定运行。进入后台,随时可能被系统回收。如果需要长时间保证运行,可以使用前台ServiceWorkManager

Activiry与Service通信

  1. 首先是自定义类继承Binder,并在Service类onBind()传入实例化的类。
class MyService : Service()
{

	private val mIBinder = DownloadBinder()

	class DownloadBinder : Binder() {}

	override fun onBind(intent: Intent) = mIBinder

}
  1. 再定义ServiceConnection,重写方法,可以从 onServiceConnected() 获得自定义的Binder。
lateinit var downloadBinder : MyService.DownloadBinder

	private val connection = object : ServiceConnection
	{
		override fun onServiceConnected(name: ComponentName?, service: IBinder)
		{
			downloadBinder = service as MyService.DownloadBinder
			// 这里写交互信息
		}

		override fun onServiceDisconnected(name: ComponentName?) {}
	}
  1. 注册、解绑
// 注册
bindService(
	Intent(this@MainActivity, MyService::class.java),
	connection,
	Context.BIND_AUTO_CREATE
)
// 解绑
unbindService(connection)

注意

任何一个Service在整个应用程序范围内都是通用的,可以和任何Activity绑定并获取相同实例。

Service 生命周期

 调用startService(),对应服务就会启动,并回调onStartCommand(),如果未创建,则优先调用onCreate()再回调

 Service是单例的,每次执行startService()也只会调用onStartCommand(),而不是创建新的实例。

 Service()只有执行了stopSelf()/stopService()或被系统回收才结束。

bindService()进行持久性连接,才会调用onBind()方法,类似地,如果服务还没有创建,依然是优先调用onCreate()

startService() / bindService() 后执行stopService() / unbindService() 就会调用onDestory(),如果两者皆调用了,那么都要执行各自解除才能**销毁(onDestory())**服务

前台Service使用方法

前台Service与Service区别

  1. 不会被系统回收
  2. 会在通知栏一直显示,还可以展开详细信息,类似于通知效果
    前台Service和Service相比,也就是在onCreat()写了一个常驻通知。但没有使用NotificationManager而是直接调用startForeground()
class MyService : Service()
{

	private val mIBinder = DownloadBinder()

	class DownloadBinder : Binder() {}

	override fun onBind(intent: Intent) = mIBinder

	@SuppressLint("NewApi")
	override fun onCreate()
	{
		super.onCreate()
		val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
		val channel = NotificationChannel(
				"my_service",
				"前台Service通知",
				NotificationManager.IMPORTANCE_HIGH
		)
		manager.createNotificationChannel(channel)

		val intent = Intent(this, MainActivity::class.java)
		startForeground(
				1, // 消息id
				NotificationCompat.Builder(
						this,
						"my_service" // 发送渠道
				).run {
					setContentTitle("标题")
					setContentText("这是一段主文本")
					setSmallIcon(R.drawable.ic_launcher_background)
					setContentIntent(
							PendingIntent.getActivity(
									this@MyService,
									0,
									intent,
									PendingIntent.FLAG_MUTABLE
							)
					)
					build()
				}
		)
	}
}
学新通

注意添加权限

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

IntentService

IntentService 废弃原因 : IntentService 受到 Android 8.0施加的所有 后台执行限制 。 替代方案 : 当运行在 Android 8.0 或者更高的版本的时候考虑使用 WorkManager 或者 JobIntentService, 利用 jobs 代替 services
这里不再介绍,而是给出如何使用Service模拟这一过程。

IntentService是为了解决一些耗时操作而诞生的,但也可以在Service开启线程,解决此问题。

class MyService : Service()
{
	...
	override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int
	{
		thread { 
			TODO("处理具体逻辑")
			// 结束服务
			stopSelf()
		}
		return super.onStartCommand(intent, flags, startId)
	}
}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgkkjji
系列文章
更多 icon
同类精品
更多 icon
继续加载