Android系统中默默的劳动者—-Service在系统中扮演了一个很重要的角色,解决了实现程序后台运行的问题,这使得应用程序即使在关闭的情况下,也可以在后台继续执行一些后台任务。 1.Service的适用场景 Service是没有界面的,所以适用于不需要和用户交互而且要长期运行的任务,比如:QQ在关闭后仍然需要一个后台程序一直监听是否有收到消息,如果有就用将消息传递到Notification,在通知栏提示有新消息。 2.Service的注意要点 (1)服务的运行不依赖任何用户界面,即使当程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能够保持正常运行。 (2)服务并不是运行在一个独立的进程中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序被杀死时,所有依赖于该进程的服务都会被停止运行。 (3)虽然Service是在后台执行的,但Service并不会自动开启一个子线程去执行耗时操作,而是默认在主线程中执行。这就需要我们在自定义的Service内部开启子线程执行具体的任务(下面会有代码举例做法)。否则直接在主线程中执行耗时操作,容易引起主线程阻塞,导致ANR异常。 (4)每个被创建的服务都是单例的,一个服务一旦被启动或者被绑定了之后,就会一直处于运行状态,只有当stopService()和unbindService()同时被调用,服务才会被销毁。 (5)只有activities,services,和contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service。 3.Service的生命周期及使用方法 上图是官方给出的Service生命周期方法的回调回程,每一个回调方法都代表了一个具体的Service状态。也可以看出根据启动方式分类可以分为两类:startServie()启动的Service(未和Activity绑定的Service)和bound Service(和Activity绑定的Service). 下面总结每个生命周期方法时的特点: (1)onCreate():第一次创建服务时被回调,如果服务已经被创建过了就不再回调此方法。 (2)onStartCommand():调用了Context的startService()方法,服务就会被启动,onStartCommand()就会被回调,所以这个回调方法是服务被启动时被系统回调的。启动之后会一直保持运行状态,直到stopService()或者stopSelf().并且每个服务只会存在一个实例,就像Activity的singleInstance(全局单例)模式一样. 初次创建:onCreate()–>onStartCommand()–>onStart() 已经创建过:onStartCommand()–>onStart() 通常在此方法中编写逻辑代码。 (3)onBind():调用Context的bindService()能获取一个服务的持久连接,这时会回调onBind()方法,如果此服务还未被创建:则onCreate()–>onBind() (4)onDestroy():服务被销毁时回调,也就是当调用了stopService()方法,onDestroy()会被执行。 那么绑定的Service当执行了unbandService()之后也会回调onDestroy(). 问题:如果一个服务显示被startService()方式启动,后又调用bindService(),这种情况如何销毁服务呢? 很简单,先取消绑定(unbindService()),再关闭该服务(stopService()或stopSelf())。 具体实现代码举例如下(布局文件略): Myservice.java:
import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MyService extends Service { final String TAG = "MyService-->"; MyBinder myBinder; public MyService() { Log.d(TAG, "MyService: "); } //当一个活动和服务绑定后就可以调用该服务的Binder提供的方法了 class MyBinder extends Binder { public void startOperate() { Log.d(TAG, "startOperate: -->"); } } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind: "); //throw new UnsupportedOperationException("Not yet implemented"); return myBinder; } @Override public void onStart(Intent intent, int startId) { Log.d(TAG, "onStart: "); super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { Log.d(TAG, "onDestroy: "); super.onDestroy(); } @Override public boolean onUnbind(Intent intent) { Log.d(TAG, "onUnbind: "); return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { Log.d(TAG, "onRebind: "); super.onRebind(intent); } }MainActivity.java:
import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import static android.R.attr.onClick; public class MainActivity extends AppCompatActivity { final String TAG = this.getClass().getSimpleName(); MyService.MyBinder myBinder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(TAG, "onServiceConnected: "); //Binder implements IBinder myBinder = (MyService.MyBinder) service; myBinder.startOperate(); } @Override public void onServiceDisconnected(ComponentName name) { Log.d(TAG, "onServiceDisconnected: "); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onClick(View v) { switch (v.getId()) { case R.id.start: Intent intent = new Intent(this, MyService.class); startService(intent); break; case R.id.stop: Intent intent1 = new Intent(this, MyService.class); stopService(intent1); break; case R.id.bind_service: Intent bindService = new Intent(this, MyService.class); /*第一第二参数很好理解,第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可*/ bindService(bindService, connection, BIND_AUTO_CREATE); break; case R.id.unbind_service: unbindService(connection); break; } } }4.IntentService的使用及与Service的差异 Service作为后台服务的实现者,虽然是解决程序后台运行的问题,但是也是有不足需要补充的。比如没有向AsyncTask类似的异步操作方法,需要手动在onStartCommand()方法中开启新的线程执行耗时任务。还有就是在任务执行完毕后没有提供自动关闭的机制,需要手动去关闭。 基于上述的不足,IntentService对Service做了很好的补充,IntentService继承于Service,官方介绍如下: 可以看出IntentService和Service的不同: (1)能处理异步请求; (2)开启新的工作线程完成耗时操作; (3)在操作完成后自动stop。 下面列举IntentService的使用:
import android.app.IntentService; import android.content.Intent; import android.util.Log; /** * created by zhiyuan at 2017/3/8 */ public class MyIntentService extends IntentService { final String TAG = MyIntentService.class.getSimpleName(); /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public MyIntentService() { super("MyIntentService"); } //子线程中执行 @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent: current thread-->" + Thread.currentThread().getId()); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy: "); } }运行结果: