Android 面试题总结之Android 基础Service(四)
在上一章节Android 面试题总结之Android 基础Broadcast Receiver(三) 我们讲了Broadcast Receiver基础知识。本节主要讲解Service相关基础知识,Service也是我们开发过程中经常使用到。
在阅读过程中有任何问题,请及时联系。如需转载请注明 fuchenxuan de Blog
本章系《Android 之美 从0到1 – 高手之路》Android基础Service 总结了Android 开发者面试比较常见的Service相关面试问题。希望对广大Android 开发者,有所帮助。
- Android 面试题总结之Android 基础Service四
- Service常见面试题
- IntentService 适用场景
Service常见面试题
- Service 是否在 main thread 中执行, service 里面是否 能执行耗时的操作?
默认情况,如果没有显示的指 servic 所运行的进程, Service 和 activity 是运 行在当前 app 所在进程的 main thread(UI 主线程)里面。
service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )
特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另 外的进程中执行
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" >
</service>
- Activity 怎么和 Service 绑定,怎么在 Activity 中启动自 己对应的 Service?
Activity 通过 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 进行绑定,当绑定成功的时候 Service 会将代理对象通过回调 的形式传给 conn,这样我们就拿到了 Service 提供的服务代理对象。
在 Activity 中可以通过 startService 和 bindService 方法启动 Service。一 般情况下如果想获取 Service 的服务对象那么肯定需要通过 bindService()方 法,比如音乐播放器,第三方支付等。如果仅仅只是为了开启一个后台任务那么 可以使用 startService()方法。
- Service 的生命周期
Service 有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不同 的使用方法生命周期方法也不同。
非绑定模式:当第一次调用 startService 的时候执行的方法依次为 onCreate()、onStartCommand(),当 Service 关闭的时候调用 onDestory 方 法。
绑定模式:第一次 bindService()的时候,执行的方法为 onCreate()、 onBind()解除绑定的时候会执行 onUnbind()、onDestory()。
上面的两种生命周期是在相对单纯的模式下的情形。我们在开发的过程中还 必须注意 Service 实例只会有一个,也就是说如果当前要启动的 Service 已经存 在了那么就不会再次创建该 Service 当然也不会调用 onCreate()方法。
一个 Service 可以被多个客户进行绑定,只有所有的绑定对象都执行了
onBind()方法后该 Service 才会销毁,不过如果有一个客户执行了 onStart() 方法,那么这个时候如果所有的 bind 客户都执行了 unBind()该 Service 也不会 销毁。
Service 的生命周期图如下所示,帮助大家记忆。
- 什么是 IntentService?有何优点?
我们通常只会使用 Service,可能 IntentService 对大部分同学来说都是第 一次听说。那么看了下面的介绍相信你就不再陌生了。如果你还是不了解那么在 面试的时候你就坦诚说没用过或者不了解等。并不是所有的问题都需要回答上来的。
一、IntentService 简介
IntentService 是 Service 的子类,比普通的 Service 增加了额外的功能。
先看 Service 本身存在两个问题:
Service 不会专门启动一条单独的进程,Service 与它所在应用位于同一个进
程中;
Service 也不是专门一条新线程,因此不应该在 Service 中直接处理耗时的
任务;
二、IntentService 特征
会创建独立的 worker 线程来处理所有的 Intent 请求;
会创建独立的 worker 线程来处理 onHandleIntent()方法实现的代码,无需
处理多线程问题;
所有请求处理完成后,IntentService 会自动停止,无需调用 stopSelf()方法
停止 Service;
为 Service 的 onBind()提供默认实现,返回 null;
为 Service 的 onStartCommand 提供默认实现,将请求 Intent 添加到队列
中;
使用 IntentService
本人写了一个 IntentService 的使用例子供参考。该例子中一个
MainActivity 一个 MyIntentService,这两个类都是四大组件当然需要在清单 文件中注册。这里只给出核心代码:
MainActivity.java: public void click(View view){ Intent intent = new Intent(this, MyIntentService.class); intent.putExtra("start", "MyIntentService"); startService(intent); } MyIntentService.java public class MyIntentService extends IntentService { private String ex = ""; private Handler mHandler = new Handler() { public void handleMessage(android.os.Message msg) { Toast.makeText(MyIntentService.this, "-e " + ex, Toast.LENGTH_LONG).show(); } }; public MyIntentService(){ super("MyIntentService"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { ex = intent.getStringExtra("start"); return super.onStartCommand(intent, flags, startId); } @Override protected void onHandleIntent(Intent intent) { /** * 模拟执行耗时任务 * 该方法是在子线程中执行的,因此需要用到 handler 跟主线程进行通信 */ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mHandler.sendEmptyMessage(0); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }
- Activity、Intent、Service 是什么关系
他们都是 Android 开发中使用频率最高的类。其中 Activity 和 Service 都是 Android 四大组件之一。他俩都是 Context 类的子类 ContextWrapper 的子类, 因此他俩可以算是兄弟关系吧。不过兄弟俩各有各自的本领,Activity 负责用户 界面的显示和交互,Service 负责后台任务的处理。Activity 和 Service 之间可 以通过 Intent 传递数据,因此可以把 Intent 看作是通信使者。
- Service 和 Activity 在同一个线程吗?
对于同一 app 来说默认情况下是在同一个线程中的,main Thread (UI Thread)。
- Service 里面可以弹吐司么
可以的。弹吐司有个条件就是得有一个 Context 上下文,而 Service 本身就是 Context 的子类,因此在 Service 里面弹吐司是完全可以的。比如我们在 Service 中完成下载任务后可以弹一个吐司通知用户。
- 什么是 Service 以及描述下它的生命周期。Service 有哪 些启动方法,有什么区别,怎样停用 Service?
在 Service 的生命周期中,被回调的方法比 Activity 少一些,只有 onCreate, onStart, onDestroy,
onBind 和 onUnbind。
通常有两种方式启动一个 Service,他们对 Service 生命周期的影响是不一样的。
- 通过 startService
Service 会经历 onCreate 到 onStart,然后处于运行状态,stopService
的时候调用 onDestroy 方法。
如果是调用者自己直接退出而没有调用 stopService 的话,Service 会一直
在后台运行。
- 通过 bindService
Service 会运行 onCreate,然后是调用 onBind,这个时候调用者和 Service 绑定在一起。调用者退出了,Srevice 就会调用 onUnbind->onDestroyed 方 法。
所谓绑定在一起就共存亡了。调用者也可以通过调用 unbindService 方法来 停止服务,这时候 Srevice 就会调用 onUnbind->onDestroyed 方法。 需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢? 一个原则是 Service 的 onCreate 的方法只会被调用一次,就是你无论多少次的 startService 又 bindService,Service 只被创建一次。
如果先是 bind 了,那么 start 的时候就直接运行 Service 的 onStart 方法,如 果先是 start,那么 bind 的时候就直接运行 onBind 方法。
如果 service 运行期间调用了 bindService,这时候再调用 stopService 的话,service 是不会调用 onDestroy 方法的,service 就 stop 不掉了,只能调用 UnbindService, service 就会被销毁
如果一个 service 通过 startService 被 start 之后,多次调用 startService 的 话,service 会多次调用 onStart 方法。多次调用 stopService 的话,service 只会调用一次 onDestroyed 方法。
如果一个 service 通过 bindService 被 start 之后,多次调用 bindService 的话, service 只会调用一次 onBind 方法。
多次调用 unbindService 的话会抛出异常。
- 通过 startService
- 在 service 的生命周期方法 onstartConmand()可不可以执行网络操作?如何在 service 中执行网络操作?
可以直接在 Service 中执行网络操作,在 onStartCommand()方法中可以执行网络操作
- 如何提高service的优先级?
Android 系统对于内存管理有自己的一套方法,为了保障系统有序稳定的运信,
系统内部会自动分配,控制程序的内存使用。当系统觉得当前的资源非常有限的时候,
为了保 证一些优先级高的程序能运行,就会杀掉一些他认为不重要的程序或者服务来释放内存。
这样就能保证真正对用户有用的程序仍然再运行。如果你的 Service 碰上了这种情况,多半会先被杀掉。
但如果你增加 Service 的优先级就能让他多留一会,
我们可以用 setForeground(true) 来设置 Service 的优先级。
为什么是 foreground ? 默认启动的 Service 是被标记为 background,当前运行的 Activity
一般被标记为 foreground,也就是说你给 Service 设置了 foreground 那么他就和正在运行的
Activity 类似优先级得到了一定的提高。当让这并不能保证你得 Service
永远不被杀掉,只是提高了他的优先级。
- service 如何定时执行?
当启动service进行后台任务的时候,我们一般的 做法是启动一个线程,然后通过sleep方法来控制进行定时的任务,如轮询操作,消息推送。这样容易被系统回收。
service被回收是我们不能控制的,但是我们可以控制service的重启活动。在service的onStartCommand
方法中可以返回一个参数来控制重启活动
使用AlarmManager,根据AlarmManager的工作原理,alarmmanager会定时的发出一条广播,然后在自己的项目里面注册这个广播,重写onReceive方法,在这个方法里面启动一个service,然后在service里面进行网络的访问操作,当获取到新消息的时候进行推送,同时再设置一个alarmmanager进行下一次的轮询,当本次轮询结束的时候可以stopself结束改service。这样即使这一次的轮询失败了,也不会影响到下一次的轮询。这样就能保证推送任务不会中断
- 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 后一定能重启。
- Service 的 onRebind(Intent)方法在什么情况下会执行?
如果在 onUnbind()方法返回 true 的情况下会执行,否则不执行。
- Activity 调用 Service 中的方法都有哪些方式?
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不能同时双向发送,两个就就能双向发送了
这里画了一个粗浅的图帮助大家理解。
**BroadCastReceiver**
- Service 如何给 Activity 发送 Message?
Service 和 Activity 如果想互发 Message 就必须使用使用 Messenger 机制。
IntentService 适用场景
- IntentService 内置的是 HandlerThread 作为异步线程,每一个交给 IntentService 的任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理
- 正在运行的 IntentService 的程序相比起纯粹的后台程序更不容易被系统杀死,该程序的优先级是介于前台程序与纯后台程序之间的
关于Service相关基础知识点,本章节就先总结到这来。希望对大家有所帮助。
水平有限,若有错漏,欢迎指正,批评,如需转载,请注明出处–http://blog.csdn.net/vfush,谢谢!