本篇文章主要讲述android servivce相关知识,其中会穿插一些其他的知识点,作为初学者的教程。老鸟绕路
目录
为什么要用Service
我们接触android的时候,大部分时候是在和activity打交道,但是有些比如网络下载、大文件读取、解析等耗时却又不需要界面对象的操作。一旦退出界面,那么可能就会变得不可控(比如界面退出后,线程通知UI显示进度,但是由于View已经被销毁导致报错,或者界面退出后下载中断,就算你写得非常完美,什么异常状态都考虑到了,还是保证不了系统由于内存紧张把你这个后台的activity给干掉,依附于于它的下载线程也中断。)
这时候Service就有它的用武之地了,不依赖界面,消耗资源少,优先级比后台activity高,不会轻易被系统干掉(就算被干掉,也有标志位设置可以让它自动重启,这也是一些流氓软件牛皮鲜的招数)、
Service及其继承者IntentService
service的生命周期
service的生命周期相对activity要简单不少。
可以看出service有两条生命线,一条是调用startService,一条是调用bindService
,两条生命线相互独立。本文只讲startService。
一道选择题,解释service生命周期的所有问题:
android通过startService的方式开启服务,关于service生命周期的onCreate()和onStart() 说法正确的是哪两项
A.当第一次启动的时候先后调用 onCreate()和 onStart()方法
B.当第一次启动的时候只会调用 onCreate()方法
C.如果 service 已经启动,将先后调用 onCreate()和 onStart()方法
D.如果 service 已经启动,只会执行 onStart()方法,不在执行 onCreate()方法
答案自己想下,结尾公布
IntentService
一些容易被忽略的基础知识:Service运行的代码是在主线程上的,也就是说,直接在上面运行会卡住UI,这时就Service的继承者(继承于Service的子类)IntentService就应运而生。android studio的新建里面直接就有IntentService的模板,足见其应用之广。
那么Service与IntentService的区别在哪呢?
详见这里 Android之Service与IntentService的比较
简单来说就是
- IntentService内部有个工作线程(Worker Thread),会将startService传入的intent通过Handler-Message机制传入工作线程,开发者通过重载onHandleIntent进行服务的具体实现。
- IntentService在跑完onHandleIntent后,如何Handler队列里没有其他消息,就会自动结束服务,有点像Thread中run函数一样,跑完run函数之后,线程就结束了。而service需要自己去停止。
一个后台计数器的例子来讲述Service
实战环节,本文通过一个计数器的例子模拟下载文件的耗时操作。
public void startService(View view){
Intent intent = new Intent(this,BackgroundService.class); intent.setAction("com.example.administrator.servicestudy.action.counter");
intent.putExtra("duration",10);
intent.putExtra("interval",1.0f);
startService(intent);
}
上述代码就是一个启动service的例子,action相当于做什么操作(适用于一个service处理多种请求的情况。),extra就是参数。参数中duration代表总时间10秒,interval代码每隔一秒。
private static final String ACTION_COUNTER = "com.example.administrator.servicestudy.action.counter";
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_COUNTER.equals(action)) {
final int duration = intent.getIntExtra(EXTRA_DURATION,0);
final float interval = intent.getFloatExtra(EXTRA_INTERVAL,0);
handleActionCounter(duration, interval)