服务(Service)

概述

进程 :进程是一个应用程序运行的载体。在Android中,进程的底层是Linux管理的。Android中应用启动的一般过程为:Linux系统创建一个进程(pid),进程里运行dvm,dvm里运行这个应用
应用程序
一个应用程序可以对应多个进程,在Android中,一个任务栈里可以有多个Activity,而Android应用程序推出后,Android会尽量将进程保留。其目的时为了下一次启动应用时提高启动速度。但这种做法容易引发内存不足的缺陷。而当内存不足时,Android会自动回收部分进程,其回收的顺序为:

  • 空进程 :没有任何组件运行,所有Activity和任务栈都已被关闭的进程
  • 后台进程 :应用程序没有服务处于运行状态,并且应用程序处于最小化的状态。当某个程序按home键返回,若该程序未启动任何服务,那么,此时进程属于后台进程
  • 服务进程 :服务进程是运行于后台的没有界面显示的进程。Android回收内存空间时会优先回收后台进程,若内存仍然不足时才回收服务进程
  • 可见进程 :应用UI可见,但失去焦点,不能操作。一般情况下这类进程很少被回收
  • 前台进程 :当前正在操作的进程,具有焦点,可以响应事件。一般情况下这类进程是不会被回收的。

服务概念

服务的概念最先是由微软引入。由上述回收机制可知,服务就是没有界面但长期运行于后台的进程。服务被回收的情况较少发生,因此,当某一应用程序不需要前台UI,但需要长期运行时可以使用服务。如音乐播放器、后台下载等。

创建服务

  • 写一个类集成Service
public class ServerDemo extends Service{
 
  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  @Override
  public void onCreate() {
  //TODO 此方法会在服务创建时调用。当服务创建完成后,将不会再调用此方法。也就是说此方法只会被调用一次
  //具体代码写在这里
  super.onCreate();
  }
  @Override
  public void onDestroy() {
  // TODO 此方法会在服务销毁时被调用
  super.onDestroy();
  //service继承了ContextWrapper类,因此,具有许多与Activity相同的方法,因此参数Context值可以是this
  //Intent intent = new Intent(this,ServerDemo.class);
  //startService(intent);    
  }
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
  // TODO 当服务被调用时执行此方法,此方法与onStart()方法相同
    return super.onStartCommand(intent, flags, startId);
  }
}
  • 然后再清单文件中application标签内配置Service
    <service android:name="com.asksky.ser.ServerDemo"></service>
  • 开启服务:服务不能自己运行,需要发送Intent开启
Intent intent = new Intent(packageContext, cls);
startService(intent);

服务的生命周期

服务只会被创建一次,如果重复被创建不会重复执行onCreate方法
服务只会被停止一次,如果服务已经停止不会重复执行onDestory方法
如果服务已经开启,多次调用startService方法,服务只会执行onstartCommand方法,onCreate方法不会执行

绑定服务

在服务中,onCreate方法会在服务被创建时执行,而onDestory方法会在服务销毁时执行.诸如此类方法都可以在一定的条件下就会被自动执行,改变某一条件就可以达到执行这些方法的目的.但是,服务中有可能存在自定义的方法,这些方法需要被调用必须手动new一个对象,但是,在Android中,四大组件一般是不会被手动创建的,因为,这些组件由Android框架创建,在内可以直接使用Context等对象,若手动创建,这些对象就不能使用了.
为了解决四大组件不能创建对象,但须调用其中方法这一问题,Android提供了绑定服务的机制。可以将Activity和服务绑定在一起,绑定过后就可以通过中间类来调用服务中的方法了。

绑定服务

bindService(intent, conn , BIND_AUTO_CREATE)
将当前Activity和Service绑定起来,用一个conn对象保持连接,在绑定时如果服务不存在则服务会被创建出来,如果服务已经存在则直接绑定.重复绑定无效果.
绑定服务将触发服务中的onBind方法
conn对象可以保持Activity和Service之间的绑定,当绑定状态发生变化时其中的方法自动被调用

移除绑定服务

unbindService(conn)
将当前Activity和Serivce的绑定解除,如果服务不再被需要则销毁(如果服务最初是被绑定时由绑定的动作而创建的则随着移除绑定销毁,如果不是则不销毁).不可以在未绑定的情况下移除绑定.
移除绑定服务将触发服务中的onUnBind方法
另外,Activity退出时,绑定自动解除了

具体实现

  • 服务类
public class MyService extends Service {
 /**
  * 在Android中,四大组件一般不能手动创建
  * 当需要调用以下自定义方法时,需要使用服务绑定机制
  * */
 public void show(){
  System.out.println("这是一个show()方法");
 }
/**
 * 写一个内部类作为service服务类与Activity类之间调用方法的中间类
 * 此类可以看做是服务类用于对外提供方法的基站
 * 可以将所有有可能被调用到的方法写进中间类,Activity类通过此类来调用具体方法
 * */
class GetService extends Binder{
  public void getShow(){
   show();
  }
  public void otherMethod(){
   Toast.makeText(MyService.this, "所有其它需要被调用的方法都可以写在此类中",0).show();
  }
 }
 /**
  * 绑定服务需要使用onBind方法,此方法用于将中间类返回
  * */
 @Override
 public IBinder onBind(Intent intent) {
  return new GetService();
 }
 
 @Override
 public void onCreate() {
  // TODO 创建服务时执行此方法
  super.onCreate();
 }
}
  • Activity类
public class MainActivity extends ActionBarActivity {
 GetService ms = null;
 /**
  * 此时,在Activity类中调用服务类中所需要的方法,就可以通过绑定服务的机制获取指定方法了
  * 服务方法中对外提供的获取方法的中间类也可以被看做一个接口,使用此接口需要先获取链接
  * 创建一个类继承ServiceConnection
  * */
 class MyServConn implements ServiceConnection{

 @Override
 public void onServiceConnected(ComponentName name, IBinder service) {
 /** 当Service中有方法被调用时,需要用到链接,此方法会执行
  * 注意必须有binder返回这个方法才有效
  * IBinder service 就是服务类中public IBinder onBind(Intent intent)方法返回的中间类
   * ComponentName name 貌似是被代理类的包名/全路径名
  */
  ms = (GetService) service;
  System.out.println(name.toString());
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
  }
 }
@Override
 protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       Intent intent = new Intent(this, MyService.class);
       bindService(intent, new MyServConn(), BIND_AUTO_CREATE);
       //ms.getShow();此处不能在onCreate方法中调用,因为此时的中间类对象为空.
   }
 public void show(View v){
       ms.getShow();
       ms.otherMethod();
   }
}

代码进阶

上述绑定服务机制存在一个小bug:中间类所有的方法都可以被调用者调用
解决方案:

  • 写一个接口
public interface IService {
    public void show();
}
  • 将中间类私有化,并继承此接口
private class GetService extends Binder implements IService{
 public void getShow(){
   show();
 }
 public void otherMethod(){
   Toast.makeText(MyService.this, "所有其它需要被调用的方法都可以卸载此类中",0).show();
   }
}

  • 此时,Activity类若直接调用中间类就会报错,此时必须调用接口,然后通过接口调用中间类中的方法,这样,只有接口中声明过的方法才可以被调用
IService ms = (IService) service;
ms.otherMethod();//此时若是调用此方法就会报错

注意:在调用服务时,若使用startService()可以启动服务,且Activity退出后,service仍然可以后台运行

但在使用绑定服务机制时,不能使用startService()方法,需要用bindService()方法来启动服务.此时,当Activity退出后,Service也会跟着退出!

解决方案

先创建服务:
  Intent intent = new Intent(this, MyService.class);
创建完成后直接启动,防止上述问题发生
  startService(intent);
当需要用到绑定服务获取方法时,再使用bindService
  bindService(intent, new MyServConn(), BIND_AUTO_CREATE);
这样,问题可以解决

相关链接:
远程服务(AIDL)

如以上内容有任何错误或补充,欢迎加QQ:1195211669 ,验证信息:简书

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容