Android笔记六Service概述
安卓多线程操作
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 异步消息处理机制
主要由四个部分构成:Message、Handler、MessageQueue和Looper
- Message
在线程传递消息,可以用what
传递一个Int,也可用arg1
和arg2
携带一些整型数据,使用obj
字段携带一个Object对象 - Handler
发送和处理消息。发送一般用sendMessgae()
、post()
方法等,发出的消息最终会传递到该的handleMessage()
中。 - MessageQueue
消息队列,主要存放所有Handle发出的消息,这些消息会一直存在,等待处理,每个线程只有一个此对象。 - 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开始,只有应用保持在前台,才能稳定运行。进入后台,随时可能被系统回收。如果需要长时间保证运行,可以使用前台Service和WorkManager
Activiry与Service通信
- 首先是自定义类继承Binder,并在
Service
类onBind()传入实例化的类。
class MyService : Service()
{
private val mIBinder = DownloadBinder()
class DownloadBinder : Binder() {}
override fun onBind(intent: Intent) = mIBinder
}
- 再定义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?) {}
}
- 注册、解绑
// 注册
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区别
- 不会被系统回收
- 会在通知栏一直显示,还可以展开详细信息,类似于通知效果
前台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
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13