龙空技术网

大厂内部面试题:Android四大组件之一Service系列

愿天堂没有代码 45

前言:

现时兄弟们对“bind可以解除绑定嘛”大概比较关怀,同学们都想要了解一些“bind可以解除绑定嘛”的相关资讯。那么小编同时在网摘上搜集了一些有关“bind可以解除绑定嘛””的相关知识,希望大家能喜欢,朋友们快快来了解一下吧!

Service-服务,Android四大组件之一,偷鸡摸狗必备功能之一。和Activity最大的区别就是多用户不可见。

Service系列问题

Service本地服务及生命周期详解

1.1 什么是Service,为什么使用Service

与Activity相对应的就是Service(服务)了,Activity在明,Service在暗。

Service 是一个可以在后台执行长时间运行的服务,对用户不可见。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行(注意:对于国内手机厂商来说,有可能切换到后台后立即就被kill,特别被压倒后台并且手机熄屏后)。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行

1.2 Android中跨进程的通信方式

源码:AndroidIPC

通过Binder绑定,在Binder中实现一系列的方法对Service进行操作: 添加一个继承Binder的内部类,并添加相应的逻辑方法 /** * 继承自Binder */ class MyBinder : Binder() { var bindService: BindService? = null; fun start() { bindService!!.startDownload() } fun stop() { bindService!!.stopDownload(); } } 重写Service的onBind方法,返回我们刚刚定义的那个内部类实例 class BindService : Service() { var binder: MyBinder? = null; override fun onCreate() { super.onCreate() binder = MyBinder(); binder!!.bindService = this; } fun startDownload() { Log.d("BindService", "startDownload"); } fun stopDownload() { Log.d("BindService", "stopDownload"); } override fun onBind(intent: Intent): IBinder { //TODO("Return the communication channel to the service.") return binder!! } } 重写ServiceConnection,onServiceConnected时调用逻辑方法 绑定服务 /** * Connection是Binder中Android进程间通信的桥梁,将IBinder对象在进程间传输 */ class BindConnection(internal var context: Context) : ServiceConnection { var binder: MyBinder? = null; var button: Button? = null; override fun onServiceConnected(name: ComponentName, service: IBinder) { this.binder = service as MyBinder Log.d("BindService", "onServiceConnected") button!!.text="绑定成功"; } override fun onServiceDisconnected(name: ComponentName) { Toast.makeText(context, "断开链接", Toast.LENGTH_SHORT).show() } } 启动时进行绑定 class Main3Activity : AppCompatActivity() { var connection: BindConnection? = null; override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main3) findViewById<View>(R.id.btn).setOnClickListener { bindIBinderService(); } findViewById<View>(R.id.btn2).setOnClickListener { connection!!.binder!!.start(); connection!!.binder!!.stop(); } } fun bindIBinderService() { connection = BindConnection(this); connection!!.button = findViewById<View>(R.id.btn) as Button; bindService(Intent(this, BindService::class.java), connection, Context.BIND_AUTO_CREATE); } override fun onDestroy() { super.onDestroy() unbindService(connection); } } BroadCastReceive Android必读之BroadcastReceive基础 Messenger 在client与Server端互相绑定Messenger可以实现两端互相通信 在Activity中实现Messenger,绑定时将对象传到Service /** * * @param messenger Activity中的Messenger,将此Messenger传递到Service中, * 从而使Service可以通过Messenger向Activity发送消息 * @param connection 链接的桥梁 */ class Main4Activity : AppCompatActivity() { var connection: MessengerConnection? = null; var handler = Handler(object : Handler.Callback { override fun handleMessage(msg: Message?): Boolean { when (msg!!.what) { 1 -> { Log.d("Main4Activity", "Receive Msg"); } else -> { } } return true; } }); var messenger: Messenger = Messenger(handler); override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main3) findViewById<View>(R.id.btn).setOnClickListener { bindMessengerService(); } findViewById<View>(R.id.btn2).setOnClickListener { var message: Message = Message.obtain(); message.what = 1; connection!!.messenger!!.send(message); } } fun bindMessengerService() { connection = MessengerConnection(this); connection!!.button = findViewById<View>(R.id.btn) as Button; var intent = Intent(this, MessengerService::class.java); intent.putExtra("Messenger", messenger); bindService( intent, connection as ServiceConnection, Context.BIND_AUTO_CREATE ); } override fun onDestroy() { super.onDestroy() unbindService(connection as ServiceConnection); } } 在Service中获取Activity中的Messenger并且把自己的Messenger通过Connect传递给Activity class MessengerService : Service() { var handler = Handler(object : Handler.Callback { override fun handleMessage(msg: Message?): Boolean { when (msg!!.what) { 1 -> { Log.d("MessengerService", "startDownload"); } 2 -> { Log.d("MessengerService", "stopDownload"); } 3, 4 -> {//同时符合3,4 } else -> { } } return true; } }); var messenger: Messenger = Messenger(handler); var activityMessenger: Messenger? = null; override fun onCreate() { super.onCreate() } override fun onBind(intent: Intent): IBinder { activityMessenger = intent.getParcelableExtra("Messenger"); var message: Message = Message.obtain(); message.what = 1; activityMessenger!!.send(message); return messenger.binder } }AIDL

1.3 介绍源码中Binder机制

答:Binder是进程间通信的具体实现,实现了IBinder接口,在BindService中接收Service中onBind(Intent intent)返回的Binder对象,通过这个Binder对象就可以对Service进行操作。这个Binder对象可以是继承自Binder类型的new出来的实例,也可以是aidl生成的AIDL.Stub对象

1.4 IntentService与Service的区别

答:IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们手动去控制或stopSelf()。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。推荐阅读:Android必读之IntentService

1.5 Service 是否在 main thread 中执行, service 里面是否 能执行耗时的操作?

默认情况,如果没有显示的指 service 所运行的进程, Service 和 activity 是运 行在当前 app 所在进程的 main thread(UI 主线程)里面。

service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )

特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另 外的进程中执行

        <service                android:name=".aidl.AidlService"                android:enabled="true"                android:process=":AidlService"                android:exported="true">
android:enabled service能否被系统实例化,默认为trueandroid:exported service能否被隐式调用 默认为trueandroid:process 是否在单独的进程中,如果没有设置值,则表明此service与UI线程在同一个进程中,并且是在主线程中。如果设置值以冒号“:”开头,则表明此service是App私有的,不能被共享;如果设置的值以小写字母开头,则表明此service是可以被系统共享的。

1.6 Service的生命周期

Service 有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不同 的使用方法生命周期方法也不同。

非绑定模式:当第一次调用 startService 的时候执行的方法依次为 onCreate()、onStartCommand(),当 Service 关闭的时候调用 onDestory 方 法。绑定模式:第一次 bindService()的时候,执行的方法为 onCreate()、 onBind()解除绑定的时候会执行 onUnbind()、onDestory()。

上面的两种生命周期是在相对单纯的模式下的情形。我们在开发的过程中还 必须注意 Service 实例只会有一个,也就是说如果当前要启动的 Service 已经存 在了那么就不会再次创建该 Service 当然也不会调用 onCreate()方法。

1.7 Service 的 onStartCommand 方法有几种返回值?各代表什么意思?

有四种返回值,不同值代表的意思如下:

START_STICKY:如果 service 进程被 kill 掉,保留 service 的状态为开始状态,但不保留递送的 intent 对象。随 后系统会尝试重新创建 service,由于服务状态为开始状态,所以创建服务后一定会调用 onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到 service,那么参数 Intent 将为 null。START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完 onStartCommand 后,服务被异常 kill 掉,系统不会自动重启该服务。START_REDELIVER_INTENT:重传 Intent。使用这个返回值时,如果在执行完 onStartCommand 后,服务被异 常 kill 掉,系统会自动重启该服务,并将 Intent 的值传入。START_STICKY_COMPATIBILITY: START_STICKY 的兼容版本,但不保证服务被 kill 后一定能重启。

1.8 Service 的 onRebind(Intent)方法在什么情况下会执行?

如果在 onUnbind()方法返回 true 的情况下会执行,否则不执行。

    /**     * Called when all clients have disconnected from a particular interface     * published by the service.  The default implementation does nothing and     * returns false.     *     * @param intent The Intent that was used to bind to this service,     * as given to {@link android.content.Context#bindService     * Context.bindService}.  Note that any extras that were included with     * the Intent at that point will <em>not</em> be seen here.     *     * @return 注意这里:Return true if you would like to have the service's     * {@link #onRebind} method later called when new clients bind to it.     */    public boolean onUnbind(Intent intent) {        return false;    }

1.9 Activity 调用 Service 中的方法都有哪些方式?

源码:AndroidIPC

Binder:

通过 Binder 接口的形式实现,当 Activity 绑定 Service 成功的时候 Activity 会在 ServiceConnection 的类 的 onServiceConnected()回调方法中获取到 Service 的 onBind()方法 return 过来的 Binder 的子类,然后通过对象调用方法。Aidl:

aidl 比较适合当客户端和服务端不在同一个应用下的场景。Messenger:

它引用了一个Handler对象,以便others能够向它发送消息(使用mMessenger.send(Message msg)方法)。该类允许跨进程间基于Message的通信(即两个进程间可以通过Message进行通信),在服务端使用Handler创建一个Messenger,客户端持有这个Messenger就可以与服务端通信了。一个Messeger不能同时双向发送,两个就就能双向发送了

之后还会不断的更新Android面试题,而且我还收集了一份关于Android架构进阶的资料,高级架构技术进阶脑图、Android开发面试专题资料等等。

如果你有需要的话,只需私信我【进阶】即可获取

喜欢本文的话,不妨顺手给我点个赞、评论区留言或者转发支持一下呗~

标签: #bind可以解除绑定嘛