Android中startService和bindService的区别

来源:互联网 发布:2017年最新网络用语 编辑:程序博客网 时间:2024/05/16 06:43

Service属于android四大组件之一,在很多地方经常被用到。开启Service有两种不同的方式:startService和bindService。不同的开启方式,Service执行的生命周期方法也不同。
首先,先看一下Service都有哪些生命周期方法。
要想使用Service需要写一个自己的MyService类,并继承Service。还要在清单文件中声明一下。

<service android:name=".MyService"/>
public class MyService extends Service {    @Nullable    @Override    public IBinder onBind(Intent intent) {        Log.e("call", "onBind");        return null;    }    @Override    public void onCreate() {        Log.e("call", "onCreate");        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("call", "onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        Log.e("call", "onDestroy");        super.onDestroy();    }}

startService开启服务和结束服务稍微简单一点。

//开启服务Intent service = new Intent(this, MyService.class);startService(service);
//结束服务stopService(service);

开启服务时,调用一次startService,生命周期执行的方法依次是:
onCreate() ==> onStartCommand();
调用多次startService,onCreate只有第一次会被执行,而onStartCommand会执行多次。
结束服务时,调用stopService,生命周期执行onDestroy方法,并且多次调用stopService时,onDestroy只有第一次会被执行。

bindService开启服务就多了一些内容。

//开启服务Intent service = new Intent(this, MyService.class);MyConnection conn = new MyConnection();//第一个参数:Intent意图//第二个参数:是一个接口,通过这个接口接收服务开启或者停止的消息,并且这个参数不能为null//第三个参数:开启服务时的操作,BIND_AUTO_CREATE代表自动创建servicebindService(service, conn, BIND_AUTO_CREATE);

bindService的方法参数需要一个ServiceConnection接口的实现类对象,我们自己写一个MyConnection类,并实现里面的方法。

private class MyConnection implements ServiceConnection{        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            //只有当我们自己写的MyService的onBind方法返回值不为null时,才会被调用            Log.e("call","onServiceConnected");        }        @Override        public void onServiceDisconnected(ComponentName name) {            //这个方法只有出现异常时才会调用,服务器正常退出不会调用。            Log.e("call","onServiceDisconnected");        }    }
//结束服务unbindService(conn);

bingService开启服务时,根据生命周期里onBind方法的返回值是否为空,有两种情况。
1、onBind返回值是null;
调用bindService开启服务,生命周期执行的方法依次是:
onCreate() ==> onBind();
调用多次bindService,onCreate和onBind也只在第一次会被执行。
调用unbindService结束服务,生命周期执行onDestroy方法,并且unbindService方法只能调用一次,多次调用应用会抛出异常。使用时也要注意调用unbindService一定要确保服务已经开启,否则应用会抛出异常。
2、onBind返回值不为null;
看一下android对于onBind方法的返回类型IBinder的介绍,字面上理解是IBinder是android提供的进程间和跨进程调用机制的接口。而且返回的对象不要直接实现这个接口,应该继承Binder这个类。
那么我们就在自己写的MyService里创建一个内部类MyBinder,让他继承Binder,并在onBind方法里返回MyBinder的对象。

@Overridepublic IBinder onBind(Intent intent) {    Log.e("call", "onBind");    MyBinder mbind = new MyBinder();    Log.e("call", mbind.toString());    return mbind;}private class MyBinder extends Binder{    public void systemOut(){        System.out.println("该方法在MyService的内部类MyBinder中");    }}

这时候调用bindService开启服务,生命周期执行的方法依次是:
onCreate() ==> onBind() ==> onServiceConnected();
可以发现我们自己写的MyConnection类里的onServiceConnected方法被调用了。调用多次bindService,onCreate和onBind都只在第一次会被执行,onServiceConnected会执行多次。
并且我们注意到onServiceConnected方法的第二个参数也是IBinder类型的,不难猜测onBind()方法返回的对象被传递到了这里。打印一下两个对象的地址可以证明猜测是正确的。
也就是说我们可以在onServiceConnected方法里拿到了MyService服务的内部类MyBinder的对象,通过这个内部类对象,只要强转一下,我们可以调用这个内部类的非私有成员对象和方法。
调用unbindService结束服务和上面相同,unbindService只能调用一次,onDestroy也只执行一次,多次调用会抛出异常。
接下来我们说一下startService和bindService开启服务时,他们与activity之间的关心。
1、startService开启服务以后,与activity就没有关联,不受影响,独立运行。ServiceConnection
2、bindService开启服务以后,与activity存在关联,退出activity时必须调用unbindService方法,否则会报ServiceConnection泄漏的错误。

最后还有一点,同一个服务可以用两种方式一同开启,没有先后顺序的要求,MyService的onCreate只会执行一次。
关闭服务需要stopService和unbindService都被调用,也没有先后顺序的影响,MyService的onDestroy也只执行一次。但是如果只用一种方式关闭服务,不论是哪种关闭方式,onDestroy都不会被执行,服务也不会被关闭。这一点需要注意。

0 0