Android: How to safely unbind a service

后端 未结 8 930
深忆病人
深忆病人 2020-12-12 16:44

I have a service which is binded to application context like this:

getApplicationContext().bindService(
                    new Intent(this, ServiceUI.class         


        
相关标签:
8条回答
  • 2020-12-12 16:46

    Here you can find a nice explanation and source codes how to work with bound services. In your case you should override methods (onServiceConnected and onServiceDisconnected) of ServiceConnection object. Then you can just check mBound variable in your code.

    0 讨论(0)
  • 2020-12-12 16:47

    I think that guide is not completely correct as mentioned here Surya Wijaya Madjid. Memory leaks can occur when bound service is destryed and not re-connected yet.

    I think that this approach is needed:

    Service mService;
    
    private final ServiceConnection mServiceConnection = new ServiceConnection()
    {
        boolean bound = false;
    
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            mService = null;
        }
    
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            mService = ((MyService.ServiceBinder) service).getService();
    
            if (!bound)
            {
                // do some action - service is bound for the first time
                bound = true;
            }
        }
    };
    
    @Override
    public void onDestroy()
    {
        if (mService != null)
        {
            // do some finalization with mService
        }
    
        if (mServiceConnection.bound)
        {
            mServiceConnection.bound = false;
            unbindService(mServiceConnection);
        }
        super.onDestroy();
    }
    
    public void someMethod()
    {
        if (mService != null)
        {
            // to test whether Service is available, I have to test mService, not     mServiceConnection.bound
        }
    }
    
    0 讨论(0)
  • 2020-12-12 16:51

    Use a variable to record if you have ever bind to a service, and unbind it if the variable is true.

    See android official example :

    http://androidxref.com/9.0.0_r3/xref/development/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.java#376

    0 讨论(0)
  • 2020-12-12 16:52

    Try this:

    boolean isBound = false;
    ...
    isBound = getApplicationContext().bindService( new Intent(getApplicationContext(), ServiceUI.class), serviceConnection, Context.BIND_AUTO_CREATE );
    ...
    if (isBound)
        getApplicationContext().unbindService(serviceConnection);
    

    Note:

    You should use same context for binding a service and unbinding a service. If you are binding Service with getApplicationContext() so you should also use getApplicationContext.unbindService(..)

    0 讨论(0)
  • 2020-12-12 16:58

    Doing exactly what Andrey Novikov proposed didn't work for me. I simply replaced:

    getApplicationContext().unbindService(serviceConnection);
    

    With:

    unbindService(serviceConnection);
    
    0 讨论(0)
  • 2020-12-12 17:04

    Why do we get this error?

    When you try to unregister a service which is not registered.

    What are some common examples?

    • Binding and Unbinding a service with different Context.
    • calling unBind(mserviceConnection) more than bind(...)

    First point is self explanatory. Lets explore the second source of error more deeply. Debug your bind() and unbind() calls. If you see calls in these order then your application will end up getting the IllegalArgumentException.

    How can we avoid this?
    There are two ways you should consider to bind and unbind a service in Activity. Android docs recommend that

    • If you want to interact with a service only when the Activity is visible then

    bindService() in onStart() and unbindService() in onStop()

    Your Activity {
    
        @Override
        public void onStart(){
           super.onStart();
           bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
        }
    
        @Override
        public void onStop(){
           super.onStop();
           unbindService(mConnection);
        }
    
    } 
    
    • If you want to interact with a service even an Activity is in Background then

    bindService() in onCreate() and unbindService() in onDestroy()

    Your Activity {
    
        @Override
        public void onCreate(Bindle sis){
           super.onCreate(sis);
            ....
            bindService(intent, mConnection , Context.BIND_AUTO_CREATE);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            unbindService(mConnection);
        }         
    
    }
    
    0 讨论(0)
提交回复
热议问题