虽然说Android 有四大组件,但是大部分Androider只会使用Activity,其他的组件只有自己踩坑学习的时候才会去弄明白。我会用代码+日志的方式帮助你理解这两种使用方式的区别。
文章目录
- 1 清单文件声明FirstService类
- 2 新增 FirstService.kt
- 3 MainActvivity启动Service
- 4 开始测试
- 4.1 startService -> stopService
- 4.2 bindService -> unBindService
- 4.3 startService -> startService -> stopService-> stopService
- 4.4 bindService -> bindService -> unBindService-> unBindService
- 4.5 startService -> bindService -> unBindService-> stopService
- 4.6 startService -> bindService -> stopService ->unBindService
- 4.7 bindService -> startService -> unBindService -> stopService
- 4.8 bindService -> startService -> stopService -> unBindService
- 4.9 (startService 或 bindService) 与Activity 的关系
- 5 总结两种启动方式
1 清单文件声明FirstService类
<application
...
<service
android:name=".FirstService"
android:enabled="true"
android:exported="false">
</service>
...
</application>
2 新增 FirstService.kt
class FirstService : Service() {
companion object{
const val TAG = "FirstService"
}
inner class MyBinder : Binder() {
val service: FirstService
get() = this@FirstService
}
override fun onCreate() {
Log.i(TAG, "onCreate")
super.onCreate()
}
override fun onBind(intent: Intent): IBinder? {
Log.i(TAG, "onBind")
return MyBinder()
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
Log.i(TAG, "start")
return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
Log.i(TAG, "onDestroy")
super.onDestroy()
}
override fun onUnbind(intent: Intent): Boolean {
Log.i(TAG, "onUnbind")
return super.onUnbind(intent)
}
}
3 MainActvivity启动Service
class MainActivity : AppCompatActivity(), View.OnClickListener {
private var mStart: Button? = null
private var mStop: Button? = null
private var mBind: Button? = null
private var mUnbind: Button? = null
private var mBinder: FirstService.FirstBinder? = null
private val mServiceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, service: IBinder) {
mBinder = (service as FirstService.FirstBinder)
}
override fun onServiceDisconnected(name: ComponentName) {
mBinder = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mStart = findViewById<View>(R.id.startService) as Button
mStop = findViewById<View>(R.id.stopService) as Button
mBind = findViewById<View>(R.id.bindService) as Button
mUnbind = findViewById<View>(R.id.unBindService) as Button
mStart!!.setOnClickListener(this)
mStop!!.setOnClickListener(this)
mBind!!.setOnClickListener(this)
mUnbind!!.setOnClickListener(this)
}
private fun stopService() {
val intent = Intent(this@MainActivity, FirstService::class.java)
stopService(intent)
}
private fun startService() {
val intent = Intent(this@MainActivity, FirstService::class.java)
startService(intent)
}
override fun onClick(v: View) {
when (v.id) {
R.id.startService -> startService()
R.id.stopService -> stopService()
R.id.bindService -> bindService()
R.id.unBindService -> unbindService(mServiceConnection)
}
}
private fun bindService() {
val intent = Intent(this@MainActivity, FirstService::class.java)
bindService(intent, mServiceConnection, BIND_AUTO_CREATE)
}
}
4 开始测试
( 我们的界面如下所示,后面的截图都是在此基础上)
前面铺垫很多啦,接下来我们开始测试!
4.1 startService -> stopService
4.2 bindService -> unBindService
4.3 startService -> startService -> stopService-> stopService
多次执行startService 并没有按照我们的常规思维多次创建 service,而是 只创建1次Service,然后重复调用onStartCommand而已,多次调用stopService也只是关闭1次 Service而已。
4.4 bindService -> bindService -> unBindService-> unBindService
和4.3相类似,多次调用bindService也是只创建1次Service
但是不会重复调用onBind, unBindService重复调用会引发Crash 需要注意
4.5 startService -> bindService -> unBindService-> stopService
注意:当点击解绑服务的时候只显示了“onUnbind”,直到点击停止服务才显示“onDestory”
4.6 startService -> bindService -> stopService ->unBindService
注意:点击停止服务的时候什么都没有打印出来,当点击解绑任务的时候才连续出现“onUnbind”“onDestory”
4.7 bindService -> startService -> unBindService -> stopService
先执行的onBind再执行的onStartCommand
注意:解绑服务时候只显示了“onUnbind”,点击停止服务的时候才显示的“onDestory”
4.8 bindService -> startService -> stopService -> unBindService
注意:停止服务的时候什么都没有显示,但是解绑服务的时候显示出了“onUnbind”“onDestory”
4.9 (startService 或 bindService) 与Activity 的关系
假设在一个 Activity中启动了MyService服务,然后再Finish 这个 Activity ,MyService该如何执行呢?
4.9.1 startService
点击"启动服务"然后退出Activity 注意并没有执行 Service的 destory方法,此时页面已经被销毁了但是Service还存在
4.9.2 bindService
点击绑定服务然后退出Activity(并没有调用unBindService方法)但是执行了Service的 Destory,此时页面已经被销毁了,Service也已经被销毁了
5 总结两种启动方式
Service只会创建一次
再次start / bind也不会创建新的Service
startService 简单粗暴,小心内存泄露
startService使用很简单粗暴但是需要关心这个Service是否应该销毁stopService
bindService使用麻烦但是功能强大
可以自动解绑和Binder通信, IPC通信(AIDL Messenger)都是基于这个 Service的 bindService
成对创建就得等成对销毁
start+bind同时创建就得等unbind+stop同时销毁, 可以理解为监听器有两个,必须都移除掉之后才可以销毁对象