二、Service详解

1.Service生命周期
微信图片_20210917161022.png

2.不同情况下生命周期情况
  1. startService/stopServie
    生命周期顺序:onCreate -> onStartCommand ->onDestroy

    • 第一次调用startService会触发onCreate和onStartCommand,以后在服务进行过程中,每次调用startService都只会触发onCreateStartCommand。
    • 不论startService次,stopService一次就能停止服务。
  2. bindService/unbindServie
    生命周期顺序:onCreate -> onBind -> onUnBind -> onDestroy
    该方法启动的服务,不论bindService调用多少次,onCeate方法只能启动一次,同时onStartCommond 方法始终不会调用。伴随启动它的Context,如果context结束了,service也会结束。

    • 第一次bindService会触发onCreate和onBind,以后的服务运行过程中,每次bindService都不会触发任何回调。
  3. 混合型(上面两种方式的交互)
    当一个Service在被启动(startService)的同时又被绑定(bindService),该Service将会一直在后台运行,并且不管调用几次,onCreate方法只会被调用一次,onStartCommand的次数和startService次数一致(使用bindService不会调用onStartCommand)。同时调用unBindService方法将不会停止Service,必须调用onStopService或Service自身的stopSelf来停止。

  4. 什么时候使用startService或者bindService或者同时使用startService和bindService?

    • a.如果只是想要一个后台服务长期进行某项任务那么使用startService便可以了。
    • b.如果想要与正在运行的Service进行联系。1.使用broadcast进行通信,如果通信比较频繁,容易造成性能上的问题,BroadcastReciver本身执行代码的时间很短,搞不好执行到一半不执行了。2.使用bindService,没有上述问题(这个时候,startService和bindService就已经同时在使用了)。
    • c.如果服务只是公开一个远程接口,提供接上的服务端(Android的Service是C/S结构)远程调用执行方法。这个时候,可以不比立即启动Service,而只用BindService,这样在第一次bindService的时候才会创建服务的实例。

3.Service的几种典型使用实例
  1. 不可交互的后台服务
    普通的Service,通过startService()方式开启。Service的生命周期:onCreate ->onStartCommand -> onDestroy。
public class BackService extends Service {
 private Thread mThread;
 @Nullable
 @Override
 public IBinder onBind(Intent intent) {
     return null;
 }
 @Override
 public void onCreate() {
     super.onCreate();
 }

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {

     mThread = new Thread() {   //执行耗时操作
         @Override
         public void run() {
             try {
                 while (true) {
                     if (this.isInterrupted()) {//等待线程停止
                         throw new InterruptedException();
                     }
                     System.out.println("执行耗时操作");
                 }
             } catch (Exception exception) {
             }
         }
     };
     mThread.start();
     return super.onStartCommand(intent, flags, startId);
 }
 @Override
 public void onDestroy() {
     super.onDestroy();
     mThread.interrupt();   //停止线程
 }
}
  1. 可交互的后台服务
    通过bindService()方式启动。Service的生命周期:onCreate -> onBind -> onUnbind -> onDestroy。与不可交互的后台服务实现步骤区别在于启动的方式和获得Service的带理对象。
//定义的Service
public class BackService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //返回myBinder对象
        return new MyBinder();
    }
    class MyBinder extends Binder{
        public void showTips(){
            System.out.println("我是binder启动的方式");
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

//-------------------在context里面调用-----------
   Intent intent = new Intent(mActivity,BackService.class);
   ServiceConnection conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder binder) {
                BackService.MyBinder myBinder = (BackService.MyBinder) binder;
                myBinder.showTips(); //进行通信
            }
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        };
        //前台调用启动服务
        bindService(intent,conn,BIND_AUTO_CREATE);
        //结束服务
        unbindService(conn);

当建立绑定后,onServiceConnected中的Service便是Service类中onBind的返回值,这样便可以调用后台服务类的方法,进行交互。

  1. 混合型后台服务
    将上面两种启动方式结合起来就是混合性交互的后台服务了。即可以单独运行后台服务,也可以运行后台服务中提供的方法,完整的生命周期是:onCreate -> onStartCommand -> onBind -> onUnibind ->onDetroy。
  2. 前台服务
    前台服务就是将服务所在的进程级别提升了。前台服务会一直有个正在运行的小图标在系统的状态栏显示,非常类似通知的效果。
    创建前台进程:
public class ForeService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        beginForeService();
    }

    private void beginForeService() {
        //创建通知
        Notification.Builder mBuilder = new Notification.Builder(this, "app")
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentText("2021-09-18")
                .setContentTitle("您有一条未读信息");
        //创建跳转到通知详情的Intent
        Intent intent = new Intent(this, MainActivity.class);
        //创建通知详情的栈
        TaskStackBuilder taskStackBuilder = TaskStackBuilder.create(this);
        //为其添加父栈,当从通知回退时,将退到添加的父栈中。
        taskStackBuilder.addParentStack(MainActivity.class);
        PendingIntent pendingIntent = taskStackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
        //设置跳转到intent中
        mBuilder.setContentIntent(pendingIntent);
        //获取通知服务
        NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //构建通知
        Notification notification = mBuilder.build();
        //显示通知
        nm.notify(0,notification);
        //启动前台服务
        startForeground(0,notification);
    }
}
//contenxt里面启动服务
startService(new Intent(this,ForeService.class));

关于TaskStackBuilder的解释: 如果没有这几行代码,点击notification后,进入对应的activity,再点击后退按钮,直接返回home界面,显然不友好,我需要返回到app的主界面(一般为MainActivity)。
TaskStackBuilder.create(this),来创建一个stackBuild实例,接下来addParentStack();,该方法的功能是为跳转后的Activity添加一个父activity,在activity中添加parentActivityName即可。

<activity
    android:name="com.lvr.service.NotificationShow" //要跳转的activity
    android:parentActivityName=".MainActivity" >  //app 的主界面
</activity

注意:通过stopForeground(),可以取消通知,即前台服务将为后台服务。此时服务依然没有停止。通过Service()可以把服务停止。

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

推荐阅读更多精彩内容

  • 一、Service简介 Service是Android程序中四大基础组件之一,它和Activity一样都是Cont...
    jimjayce阅读 515评论 0 0
  • 一、Service简介 Service是Android程序中四大基础组件之一,是在后台运行的组件。 Service...
    提升即效率阅读 906评论 0 1
  • 什么是Service 先看一下google官方的介绍: Service是一个可以在后台执行长时间运行操作而不提供用...
    Cris_Ma阅读 756评论 0 0
  • 生命周期 从图中可以看出Service的生命周期会根据启动方式的不同有不同的生命周期回调。两种启动方式分别是sta...
    Vinson武阅读 502评论 0 1
  • onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,不管怎样...
    一只好奇的茂阅读 1,752评论 0 18