有关Service的startService与bindService在各种情形下生命周期的变化

来源:互联网 发布:vb眼镜正品多少钱 编辑:程序博客网 时间:2024/05/20 05:27

Activity模版:

public class MainActivity extends AppCompatActivity{    private ServiceConnection connection=new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            log("onServiceConnected");        }        @Override        public void onServiceDisconnected(ComponentName name) {            log("onServiceDisconnected");        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.layout_main);        log("onCreate");    }    public void click1(View view) {        int id = view.getId();        switch (id) {            case R.id.bt_1_1:                log("click -> startService");                startService(new Intent(this,MyService.class));                break;            case R.id.bt_1_2:                log("click -> stopService");                stopService(new Intent(this,MyService.class));                break;            case R.id.bt_1_3:                log("click -> bindService");                bindService(new Intent(this,MyService.class),connection,BIND_AUTO_CREATE);                break;            case R.id.bt_1_4:                log("click -> unbindService");                unbindService(connection);                break;            case R.id.bt_1_5:                log("click -> to next activity");                startActivity(new Intent(this,Main2Activity.class));                break;            default:        }    }    @Override    protected void onDestroy() {        super.onDestroy();        log("onDestroy");    }    private void log(String msg) {        Log.d("TAG-MainActivity", msg);    }}

Service设置:

public class MyService extends Service {    private MyBinder binder = new MyBinder();    @Override    public void onCreate() {        super.onCreate();        log("onCreate");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        log("onStartCommand");        return super.onStartCommand(intent, flags, startId);    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        log("onBind");        return binder;    }    @Override    public boolean onUnbind(Intent intent) {        log("onUnbind");        return super.onUnbind(intent);    }    @Override    public boolean bindService(Intent service, ServiceConnection conn, int flags) {        log("bindService");        return super.bindService(service, conn, flags);    }    @Override    public void unbindService(ServiceConnection conn) {        super.unbindService(conn);        log("unbindService");    }    @Override    public void onDestroy() {        super.onDestroy();        log("onDestroy");    }    @Override    public boolean stopService(Intent name) {        log("onDestroy");        return super.stopService(name);    }    private void log(String msg) {        Log.d("TAG-MyService", msg);    }    static class MyBinder extends Binder {    }}

说明:有三个Activity,分别为MainActivity、Main2Activity、Main3Activity,这三个Activity 的实现完全复制于上述模版,只不过Main3Activity中跳转到下一个Activity的点击事件实际的实现。


接下来,将会对各种情景进行实践,观察Service的生命周期变化。

(说明:红色框代表第一个Activity,即MainActivity,黄色的代表Main2Activity,蓝色代表Main3Activity,箭头向下表示从当前Activity跳转到下一个Activity,箭头向上则表示把当前Activity 推出栈回到上一个Activity,框内的表示当前Activity对同一个Service的操作,空白表示不做任何操作。当然最后都会把第一个Activity推出栈并回到桌面)

情景:


1、

这里写图片描述

这里写图片描述

先有一个Activity startService(跳转到后面当Activity时没有被销毁,只能被压到了栈底),之后有多个Activity bindService,然后跳转带最后一个Activity时,先bindService,然后直接stopService,之后再依次将Activity推出栈,从上面的运行截图可以看到,当Service被stopService,Service没有立即被销毁,然后一直等到了最初bindService的Activity被销毁之后(从日志可以看到先MainActivity被onDestory然后才是Service被onDestory),Service才被销毁,此时也没有对startService的Activity做任何操作。


2、

这里写图片描述
这里写图片描述
这次是在第一个Activity中bindService,在第二个中startService,再最后一个中bindService,然后回退Activity的时候在最后一个中unbindService,第二个不错操作,回到第一个unbindService,最后把第一个也推出栈,然后从运行日志中可以看到,在最后Service没有执行onDestory方法,也就是表明Service还存在,没有被销毁,这一点从日志画红圈的部分(重新进入第一个Activity并startService)也可以得以验证。


3、

这里写图片描述
这里写图片描述
这一次只是单单在两个Activity中执行bindService以及unbindService操作,可以看到,此时在第一个Activity销毁前,Service已经在执行了unbindService操作后被销毁了,与(1)存在些许区别。


4、

这里写图片描述
这里写图片描述
在这次的尝试中,从输出的日志可以看到,当在第二个Activity中stopService之后,Service没有被立即销毁,而是一直等到第一个Activity被onDestory之后(也就是最后一个与其绑定的Context销毁之后),它才自动被销毁,情况和(1)类似。


5、

这里写图片描述
这里写图片描述
在这一次的尝试中,可以看到,最后在第一个Activity中执行完unbindService之后,Service正常的被销毁。


6、

这里写图片描述
这里写图片描述
根据运行流程与输出的日志可以看到,虽然在第二个Activity中没有unbindService,但是当第二个Activity onDestory之后,其绑定到Service中的Context也就失效了,然后回到第一个Activity中执行unbindService之后,Service就立即被销毁了。


7、

这里写图片描述
这里写图片描述
这次在第一个Activity中unbindService之后,Service也被正常销毁了。


8、

这里写图片描述
这里写图片描述
这次,在第二个Activity中startService后没有进行stopService,在第三个Activity中bindService后也没有unbindService,只有在第一个Activity推出栈之前执行unbindService,从运行日志可以看出,Service没有被销毁,还处于运行状态(从画圈部分的日志可以得以验证,再次进入程序,在第一个Activity中startService并没有执行onCreate只执行了onStartCommand)。


9、

这里写图片描述
这里写图片描述


10、

这里写图片描述
这里写图片描述
如果只是在第一个Activity中bindService,然后在把Activity推出栈,在Activity执行onDestory之后,Service才自动执行unbindService然后被销毁。


11、

这里写图片描述
这里写图片描述


根据上述的几个情景的验证,可以得出如下结论:


【1】当startService单独使用时,即使对应的startService时传入的Context被销毁,Service也还是会处于运行状态。


【2】无论多少个Activity绑定了Service,但是onBind()只会执行一次,也就是Service首次被绑定时会执行,onUnbind()也是如此,即最后一个Context失效后,才会执行onUnbind()(Activity主动调用unbindService或者被onDestory)。
而如果由于Activity没有主动调用unbindService与Serivice解绑,这样会造成内存泄漏。如截图:
这里写图片描述
(这里需要说明的是,只要Activity在bindService后,如果在销毁前没有主动调用unbindService,就会引发内存泄漏。)

最后一个Context的意思是所有Context中最后一个失效的Context,假设有两个Activity,都绑定了Service,且在从第一个Activity跳转带第二个Activity,当在第二个Activity中bindService后,借助广播或者其他途径直接finish掉第一个Activity(可以在第一个Activity被销毁前先unbindService),这样,在第二个Activity与Service绑定时传入的Context就成了最后一个Context了。


【3】当只有一个Activity与Service进行bindService而没有startService,则Activity在onDestory前如果没有主动调用unbindService与Service解除绑定,或者只是直接调用stopService,则需要等到Activity被销毁,也就是与Service绑定的Context失效时,Service才会执行onUnbind(),之后会自动调用onDestory()进行销毁。


【4】
如果是多个Activity都绑定了同一个Service绑定,且没有执行过startService,当其中一个Activity onDestory或者进行unbindService之后,其与Service进行bindService时的Context就会失效,而当最后与Service绑定的Contxet失效后,Service才会执行onUnbind(),之后会自动调用onDestory()进行销毁。


【5】
如果是同时有多个Activity对Service进行了startServicebindService,如果没有显示调用过stopService,则当所有与Service绑定的Context失效后,Service不会被销毁,会一直在后台运行,因为有主动调用了startService,此时必须主动调用stopService或者在Service中调用stopSelf才能将其销毁;而如果在一个或者多个Context失效前主动调用了stopService或者在Service中调用stopSelf,则需要等到最后一个Context主动与Service进行unbindService或者失效后,才会能使Service执行onDestory

阅读全文
0 0
原创粉丝点击