Android四大组件之Service

Service的两种启动方式以及生命周期

第一种方式:

通过start方式开启服务

使用service的步骤:

  1. 定义一个类继承Service;
  2. manifest.xml文件中配置Service;
  3. 使用context.startService(Intent)启动Service;
  4. 不使用时,调用context.stopService(Intent)停止服务;

使用start方式启动的生命周期:
onCreate() -> onStartCommand() -> onDestory()
如果Service已经开启,不会重复回调onCreare(),如果再次调用context.startService(),Service会调用onStart()onStartCommand()。停止Service调用context.stopService(),停止的时候回调onDestroy()销毁。

特点:
服务开启后就跟调用者(开启者)没有任何关系了。如果开启者退出或者挂了,服务还在后台长期的运行,开启者不能调用服务里面的方法。

第二种启动方式

通过bind的方式开启服务

使用Service的步骤:

  1. 定义一个类继承Service
  2. manifest.xml文件中注册service
  3. 使用context的bindService(Intent,ServiceConnection,int)方法启动service
  4. 不再使用时,调用unbindService(ServiceConnection)方法停止该服务

使用bind方式启动的生命周期:

onCreate() -- > onBind() --> onUnbind() -- > onDestroy()

特点:
bind方式开启服务,绑定服务,调用者挂了,服务也跟着挂掉。绑定着可以调用服务里面的方法。

本地服务(LocalService)

调用者和Service在同一个进程里,所以运行在主线程的main线程中。所以不能进行耗时操作,可以采用在Service里面创建一个Thread来执行任务。Service影响的是进程的生命周期,讨论与Thread的区别没有意义。
任何Activity都可以控制同一Service,而系统也只会创建一个对应Service的实例。

示例代码:
  1. 定义一个类继承Servive
class TestService : android.app.Service() {
    private val TAG = "TestService"

    override fun onCreate() {
        super.onCreate()
        Log.i(TAG, "onCreate")
    }

    override fun onStart(intent: Intent, startId: Int) {
        super.onStart(intent, startId)
        Log.i(TAG, "onStart")
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        Log.i(TAG, "onStartCommand")
        return super.onStartCommand(intent, flags, startId)
    }

    //绑定服务时调用这个方法,返回一个IBinder对象
    override fun onBind(intent: Intent): android.os.IBinder? {
        Log.i(TAG, "onBind")
        return TestBinder()
    }

    override fun onUnbind(intent: Intent): Boolean {
        Log.i(TAG, "onUnbind")
        return super.onUnbind(intent)
    }

    //    停止服务,通过调用Context.unbindService(),别忘了service也继承了Context类
    override fun unbindService(conn: ServiceConnection) {
        super.unbindService(conn)
        Log.i(TAG, "unbindService")
    }

    //服务挂了
    override fun onDestroy() {
        super.onDestroy()
        Log.i(TAG, "onDestroy")
    }


    inner class TestBinder : Binder() {

        fun stopService(serviceConnection: ServiceConnection) {
            unbindService(serviceConnection)
        }


        fun runTask() {
            for (i in 0..9) {
                Log.i(TAG, "service is opening")
            }
        }
    }

}
  1. manifest.xml文件中注册
        <service
                android:name=".TestService"
                android:exported="true">
            <intent-filter>
                <action android:name="com.test.myservice.TestService"/>

                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

  1. 绑定Service
class ServiceActivity : AppCompatActivity() {
    private lateinit var serviceBinding: ActivityServiceBinding
    private lateinit var intents: Intent
    private lateinit var serviceConnection: TestServiceConnection
    private lateinit var binder: TestService.TestBinder

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_service)
        serviceBinding = DataBindingUtil.setContentView(this, R.layout.activity_service)

        initView()
    }

    private fun initView() {
        /**
         * 开启服务
         * */
        start_service.setOnClickListener {
            intents = Intent(this@ServiceActivity, TestService::class.java)
            startService(intents)
        }
        /**
         * 停止服务
         * */

        stop_service.setOnClickListener { stopService(intents) }
        /**
         * 绑定服务
         * */

        bind_service.setOnClickListener {
            intents = Intent(this@ServiceActivity, TestService::class.java)

            serviceConnection = TestServiceConnection()
            bindService(intents, serviceConnection, Context.BIND_AUTO_CREATE)
        }
        /**
         * 解绑服务
         * */

        unBind_service.setOnClickListener { unbindService(serviceConnection) }

    }


    internal inner class TestServiceConnection : ServiceConnection {

        //这里的第二个参数IBinder就是Service中的onBind方法返回的
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            Log.i("TestService", "onServiceConnected")

            binder = service as TestService.TestBinder

            binder!!.runTask()
        }

        override fun onServiceDisconnected(name: ComponentName) {
            Log.i("TestService", "onServiceDisconnected")
        }
    }
}

startService生命周期

2018-12-03 15:07:53.921 14516-14516/com.test.myservice I/TestService: onCreate
2018-12-03 15:07:53.930 14516-14516/com.test.myservice I/TestService: onStartCommand
2018-12-03 15:07:53.930 14516-14516/com.test.myservice I/TestService: onStart
2018-12-03 15:07:56.097 14516-14516/com.test.myservice I/TestService: onDestroy

bindService生命周期

2018-12-03 15:07:58.089 14516-14516/com.test.myservice I/TestService: onCreate
2018-12-03 15:07:58.090 14516-14516/com.test.myservice I/TestService: onBind
2018-12-03 15:07:58.091 14516-14516/com.test.myservice I/TestService: onServiceConnected
2018-12-03 15:07:58.091 14516-14516/com.test.myservice I/TestService: service is opening
2018-12-03 15:07:58.091 14516-14516/com.test.myservice I/TestService: service is opening
2018-12-03 15:08:01.082 14516-14516/com.test.myservice I/TestService: onUnbind
2018-12-03 15:08:01.083 14516-14516/com.test.myservice I/TestService: onDestroy

远程服务(AIDL)

调用者和Service不在同一个进程中,Service在单独的进程中的main线程,是一种跨进程通信方式。

绑定远程服务的步骤:

  1. 在服务的内部创建一个内部类,提供一个方法,可以间接调用服务的方法
  2. 把暴露的接口文件的扩展名改为.aidl文件 去掉访问权限
  3. 实现服务的onbind(),继承Bander和实现aidl定义的接口,提供给外界可调用的方法
  4. 在Activity中绑定服务bindService()
  5. 在服务成功绑定的时候回调onServiceConnected()传递一个IBinder对象
  6. aidl定义的接口.Stub.asInterface(binder)调用接口里面的方法

示例代码:

  1. 定义一个Service
class ProcessService : Service() {

    val TAG: String = "ProcessService"
    override fun onBind(intent: Intent?): IBinder? {
        return ProBinder()
    }

    fun methodInService() {
        Log.i(TAG, "服务里的方法执行了")
    }

    inner class ProBinder :ProcessBinder.Stub(){
         override fun invokeMethodInMyService() {
             methodInService()
         }

     }

    }
  1. 创建ProcessBinder.aidl 文件
interface ProcessBinder {
     void invokeMethodInMyService();

}
  1. 调用远程服务
/**
         *
         * 绑定远程服务
         * */
        bind_process_service.setOnClickListener {

            intentProcess = Intent(this, ProcessService::class.java)
            processConnection = ProcessConnection()
            bindService(intentProcess, processConnection, Context.BIND_AUTO_CREATE)


        }

        /**
         * 调用服务方法
         * */
        onclick_pro_service.setOnClickListener {
            proBinder.invokeMethodInMyService()
        }


	internal inner class ProcessConnection : ServiceConnection {

        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            //通过Stub得到接口类型
            proBinder = ProcessBinder.Stub.asInterface(service)
        }

        override fun onServiceDisconnected(name: ComponentName) {
        }
    }

按运行地点分类特点优点缺点应用场景
本地服务1. 运行在主线程
2. 主线程被终止后,服务也终止
1. 节约资源
通信方便,在同一进程不需要IPC和aidl
限制性大:主进程被终止,服务进程也会终止需要依赖某个进程的服务,如音乐播放
远程服务1. 运行在独立进程
2. 服务常驻在后台,不受其它Activity影响
灵活:服务常驻在后台,不受其它Activity影响1. 消耗资源:单独进程
2. 使用aidl进行IPC复杂
系统级别服务
运行类型分类特点应用场景
前台服务在通知栏显示通知
(用户可以看到)
服务使用需要让用户知道并进行相关操作,如音乐播放服务
(服务被终止的时候,通知栏的通知也会消失)
后台服务处于后台的服务
(用户无法看到)
服务使用时不需要让用户知道并进行相关操作,如天气更新,日期同步
(服务被终止的时候,用户是无法知道的)
按功能分类特点应用场景
不可通信的后台服务1. 用startService启动
2. 调用者退出service任然存在
该后台服务不进行任何通讯
可通信的后台服务1. 用bindService启动
2. 调用者退出,随着调用者销毁
该后台服务需要进行通讯
IntentService

Intentservice 是Service的子类,比普通的Service 增加了额外的功能。
Service 本身存在两个问题:

  • Service 不会专门启动一条单独的进程,Service与它所在应用位于同一个进程;
  • Service 也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务;

IntentService 特征:

  • 会创建独立的worker线程来处理所有的Intent请求;
  • 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
  • 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;
  • 为Service的onBind()提供默认实现,返回null;
  • 为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值