美文网首页
2、Service

2、Service

作者: Leo_JiangZhiHao | 来源:发表于2023-09-22 17:40 被阅读0次
    Service和Thread的区别

    既然是长耗时的操作,那么Thread也可以完成啊。没错,在程序里面很多耗时工作我们也可以通过Thread来完成,那么还需要Service干嘛呢?

    • Service可以重写onStartCommand,使得Service被杀掉之后,Service能自动重启,Thread做不到。
    • Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。
    Service与Activity怎么实现通信
    • 通过Binder对象(AIDL):Activity调用bindService()方法,绑定一个继承Service的引用对象MyService。通过实例化ServiceConnection接口内部类监听的方法获取MyService中的Binder对象。如果想实现主动通知Activity的,还可以在MyService中添加回调方法。(例子代码如下)
    • 通过广播:Activity调用registerReceiver(BroadcastReceiver recevier, IntentFilter filter)注册广播接收器,通过startService(Service service)启动一个集成Service的应用对象MsgService,之后MsgService可通过sendBoadcast(Intent intent)更新Actvity内容信息。
    public class MyService extends Service {
    
        private DownloadBinder mBinder = new DownloadBinder();
    
        class DownloadBinder extends Binder {
            public void startDownload() {
                Log.d("MyService", "startDownload executed");
                downloadCore();
            } // 在Service中自定义startDownload方法,后续在Activity中调用此方法
    
            public int getProgress() {
                Log.d("MyService", "getProgress executed");
                return 0;
            } // 在Service中自定义getProgress方法,后续在Activity中调用此方法
    
            public MyService getService() {
                return MyService.this;
            } // 在Service中自定义getService方法,后续在Activity中调用此方法,获得MyService对象以设置回调
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return mBinder;
        }
    
        private void downloadCore() {
            if (null != listener) {
                listener.notifyProgress(0);
            }
        }
    
        private OnProgressListener listener;
    
        public void setOnProgressListener(OnProgressListener listener) {
            this.listener = listener;
        }
    
        interface OnProgressListener {
            void notifyProgress(int progress);
        }
        ......
    }
    
    public class MainActivity extends AppCompatActivity {
    
        private MyService.DownloadBinder downloadBinder;
    
        private ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                downloadBinder = (MyService.DownloadBinder) service;
                downloadBinder.startDownload();
                downloadBinder.getProgress();
    
                MyService myService = downloadBinder.getService();
                myService.setOnProgressListener(new MyService.OnProgressListener() {
                    @Override
                    public void notifyProgress(int progress) {
                        Log.d("MyService", "notifyProgress executed");
                    }
                });
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button bindServiceBtn = findViewById(R.id.button1);
            Button stopServiceBtn = findViewById(R.id.button2);
            bindServiceBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent = new Intent(MainActivity.this, MyService.class);
                    bindService(intent, connection, Context.BIND_AUTO_CREATE);
                }
            });
            stopServiceBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    unbindService(connection);
                }
            });
        }
    }
    
    Service的生命周期,两种启动方式(startService、bindService)的区别
    生命周期.png
    • 被启动的服务的生命周期:如果一个Service被某个Activity调用Context.startService方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService方法多次启动,那么onCreate方法只会调用一次,onStartCommand将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例(因此你应该知道只需要一次stopService调用)。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
    • 被绑定的服务的生命周期:如果一个Service被某个Activity调用Context.bindService方法绑定启动,不管调用bindService调用几次,onCreate和onBind方法都只会调用一次(不调用unbindService),同时onStartCommand方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService断开连接或者之前调用bindService的Context不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。
    • 被启动又被绑定的服务的生命周期:如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStartCommand便会调用多少次。必须调用unbindService和stopService来停止服务。
    • 当服务被停止时清除服务:当一个Service被终止(①调用stopService;②调用stopSelf;③不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

    startService、bindService的区别:举一个简单的例子,最常用的Service就是音乐播放,如果你要startService的话,应用退出了,音乐还在播放。用bindService的话,程序退出了,音乐也就停了。

    bindService和startService混合使用的生命周期以及怎么关闭

    举两个混用的例子,未加粗的是Activity中的调用,加粗的是Service的生命周期:

    • startService → onCreateonStartCommand → bindService → onBind → stopService → unbindService → onUnbindonDestroy
    • bindService → onCreateonBind → startService → onStartCommand → unbindService → onUnbind → stopService → onDestroy

    只有当stopService和unbindService都被调用,Service才会调用onDestroy,Service的生命周期才会结束。

    Service的onStartCommand方法有几种返回值?各代表什么意思?

    在Service中重写onStartCommand方法,可以使得Service被杀死(比如杀掉apk)之后自动重启。

    • START_STICKY 粘性的:如果Service被杀死之后,系统会自动重启该服务,但是不会保留之前传递过来的intent对象。
    • START_NOT_STICKY 非粘性的:Service被杀死之后,系统不会自动重启该Service。
    • START_REDELIVER_INTENT 重传intent:Service被杀死之后,系统会自动重启该服务,并且保留之前的intent传入(就是比START_STICKY多了一个intent)。
    • START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但是不保证Service一定能重启。
    IntentService是什么、原理、应用场景及其与Service的区别
    • 是什么:如果直接把耗时操作放在Service的onStartCommand()中,很容易引起ANR。IntentService是继承于 Service 并处理异步请求的一个类,在IntentService内有一个子线程来处理耗时操作,通过 startService(intent)启动服务,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制或stopSelf()。
      另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个子线程,执行完第一个再执行第二个,以此类推。
    public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            for (int i = 1; i <= 20; i++) {
                Intent intent = new Intent(this, MyIntentService.class);
                startService(intent);
            }
        }
    
        ......
    }
    
    • 原理:IntentService本质是采用Handler & HandlerThread方式:(源码如下)
      ①通过HandlerThread单独开启一个名为IntentService的线程。
      ②创建一个名为ServiceHandler的Handler。
      ③把内部Handler与子线程HandlerThread的Looper进行绑定。
      ④通过onStartCommand()传递给服务intent,依次插入到工作队列中,并逐个发送给onHandleIntent()。
      ⑤通过onHandleIntent()来依次处理所有Intent请求对象所对应的任务。
      注意:多次启动IntentService不会重新创建新的服务和新的线程,而是把消息加入消息队列中等待执行,而如果服务停止,会清除消息队列中的消息,后续的事件便不会执行。
        @Override
        public void onCreate() {
            // TODO: It would be nice to have an option to hold a partial wakelock
            // during processing, and to have a static startService(Context, Intent)
            // method that would launch the service & hand off a wakelock.
    
            super.onCreate();
            HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
            thread.start();
    
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);
        }
    
    • 应用场景:解决多个耗时任务需要顺序依次执行的问题。而如果仅用Service,开多个线程去执行耗时操作,就很难管理。例如排队下载,一个下载完的时候需要自动去下载下一个,下载完后自动关闭任务。
    • 区别:
      ①IntentService是继承自Service类,创建了自己的特有方法onHandleIntent:每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,执行完第一个再执行第二个.
      ②每次IntentService执行完任务都会自动停止,而不需要我们手动去控制或stopSelf()。
      ③IntentService每次执行都开启一个子线程。(连续执行耗时操作除外)

    相关文章

      网友评论

          本文标题:2、Service

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