Service的两种启动模式

Service有两种启动模式,startService 和bindService

两种模式下的生命周期如下:(借用了Big不吃鱼的https://www.jianshu.com/p/4c798c91a613)

Service的两种启动模式_第1张图片

一、startService模式

通过这种方式调用startService,onCreate只会被调用一次,多次调用startSercie会多次执行onStartCommand()和onStart()方法。如果外部没有调用stopService()或stopSelf()方法,service会一直运行。

示例:

public class AppService extends Service {
    private static final String TAG ="AppService";

    //多次调用startService只会调用一次onCreate方法
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG,"onCreate ,threadId ="+Thread.currentThread().getId());
    }

    //多次调用startService方法,会多次调用onStartCommand
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG,"onStartCommand  startId ="+startId +", threadId ="+Thread.currentThread().getId());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.i(TAG,"onStart , threadId ="+Thread.currentThread().getId());
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,"onBind.....");
        return null;
    }


    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG,"onUnbind.....");
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG,"onDestroy threadId ="+Thread.currentThread().getId());
    }
}

在Activity中通过startService启动和销毁service

public class TestActivity extends Activity implements View.OnClickListener{

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
    }


    @Override
    public void onClick(View view) {
        Intent intent = null;
        switch (view.getId()){
            case R.id.button1:
                intent = new Intent(this,AppService.class);
                startService(intent);
                break;
            case R.id.button2:
                intent = new Intent(this,AppService.class);
                stopService(intent);
                break;
        }
    }
}

点击button1多次startService,然后点击button2销毁service,运行结果如下:

Service的两种启动模式_第2张图片

结论:多次调用startService只会产生一个service对象

二、bindService模式

    当需要Activity Fragment与Service有交互操作时,一般选择bindService。通过IBinder接口获取Service对象,这样就可以调用Service中的方法,比如有些耗时的操作可以放在service中。

    bindService方式下,service的生命周期与其绑定的组件(如Activity)相关联,如果组件调用了unbindService(),则Servcie会销毁,如果组件未调用该方法,则service随着其被绑定组件销毁而销毁。没有组件绑定service,它会自行销毁。

   可以有一个或者多个组件绑定service。

 第一步:首先在AppSercie中创建IBind接口,返回service实例。

private LocalBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
        public AppService getService(){
            return AppService.this;
        }
}    
public IBinder onBind(Intent intent) { Log.i(TAG,"onBind....."); return mBinder; }

添加一个可以供外部调用的方法。

public void printSimpleTime(){
        for (int i=0 ; i<10; i++){
            try{
                Thread.sleep(100);
                Log.i(TAG,"i ="+i +",currentTime ="+System.currentTimeMillis());
            }catch (InterruptedException e){
                e.getStackTrace();
            }
        }
    }

创建一个BaseActivity基类,添加bindService、unbindService方法

public class BaseActivity extends Activity {
    protected AppService mService;
    private ServiceConnection mServiceConnection;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void bindService(){
        if (mServiceConnection==null){
            mServiceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                    Log.i("AppService","onServiceConnected ------");
                    mService = ((AppService.LocalBinder) iBinder).getService();
                }

                @Override
                public void onServiceDisconnected(ComponentName componentName) {
                    Log.i("AppService","onServiceDisconnected =======");
                    mService = null;
                }
            };
        }
        bindService(new Intent(this,AppService.class),mServiceConnection, Context.BIND_AUTO_CREATE + Context.BIND_DEBUG_UNBIND);
    }

    public void unbindService(){
        if (mServiceConnection!=null){
            Log.i("AppService","unbindService =======");
            unbindService(mServiceConnection);
            mServiceConnection = null;
        }
    }
}

(注:bindService第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可)

然后再添加类继承BaseActivity,调用bindService(),获得service对象

public class BindServcieActivityA extends BaseActivity implements View.OnClickListener{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bindservice_a);
        findViewById(R.id.bindButton).setOnClickListener(this);
        findViewById(R.id.unbindButton).setOnClickListener(this);
        findViewById(R.id.finishButton).setOnClickListener(this);
        findViewById(R.id.optionButton).setOnClickListener(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bindButton:
                bindService();
                break;
            case R.id.unbindButton:
                unbindService();
                break;
            case R.id.finishButton:
                this.finish();
                break;
            case R.id.optionButton:
                if (mService!=null){
                    mService.printSimpleTime();
                }
                break;
        }

    }

测试步骤:

1、点击bindButton,然后点击unbindButton,测试结果如下:

Service的两种启动模式_第3张图片

可以看出bindService的生命周期:

(1)当调用bindService时:onCreate -> onBind

         

BindServcieActivityA类中,ServiceConnection执行onServiceConnected()方法

(2)调用unbindService时,onUnbind ->onDestroy

2、bindService之后,直接finish()当前Activity,运行结果如下:

Service的两种启动模式_第4张图片

可以看到直接finish(),不会调用unbindService方法,Service在Activity销毁后,自行解除绑定然后销毁。

3、当调用bindService后,获取到AppService实例对象,通过对象调用AppServcie中的printSimpleTime()方法。

(注:当调用unbindService方法时,不会调用onServiceDisonnected(),只有当Service的连接意外丢失才会用到这个方法,比如Service被强杀或崩溃)

4、用同样的方法创建一个BindServiceActivityB

public class BindServiceActivityB extends BaseActivity implements View.OnClickListener{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bindservice_b);
        findViewById(R.id.bindBtn).setOnClickListener(this);
        findViewById(R.id.unbindBtn).setOnClickListener(this);
        findViewById(R.id.printBtn).setOnClickListener(this);
    }


    @Override
    protected void onStart() {
        super.onStart();
//        bindService();
    }

    @Override
    protected void onStop() {
        super.onStop();
//        unbindService();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.bindBtn:
                bindService();
                break;
            case R.id.unbindBtn:
                unbindService();
                break;
            case R.id.printBtn:
                if (mService!=null){
                    mService.printSimpleTime();
                }
                break;
        }

    }
}

测试步骤:

1)BindServiceActivityA先调用bindService()

2)跳转到BindServiceActivityB,依次调用bindServie(),printSimpleTime(),unbindService()

3)返回到BindServiceActivityA,调用unbindService()

Service的两种启动模式_第5张图片

step1:执行了Service的onCreate ->onBind,BindServcieActivityA执行onServiceConnected方法,获取了IBinder对象;

setp2:当前BindServcieActivityA已经与AppService建立绑定的情况下,BindServcieActivityB不会重新创建IBinder对象,直接调用onServiceConnected进行绑定,两者共享一个IBInder实例对象;调用unbindService(),解除了当前组件与Service的绑定关系。当Service没有与任何组件绑定的情况下,才会调用onUnbind方法。此时,BindServcieActivityA还在绑定连接中,所以不会执行Service的解绑方法

step3:BindServcieActivityA调用unbindService(),执行onUnbind - >onDestroy

你可能感兴趣的:(Android)