美文网首页
二、Service详解

二、Service详解

作者: 木小伍 | 来源:发表于2021-09-18 09:23 被阅读0次
    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()可以把服务停止。

    相关文章

      网友评论

          本文标题:二、Service详解

          本文链接:https://www.haomeiwen.com/subject/drksgltx.html