美文网首页
Android - Service Bind/Unbind 使用

Android - Service Bind/Unbind 使用

作者: 拾识物者 | 来源:发表于2019-03-29 07:37 被阅读0次

    Service Bind/Unbind 使用方式

    本文介绍了本地服务,也就是同一个进程内的服务,如何使用 Bind/Unbind 方式被 Activity 使用。

    本文不涉及 AIDL 使用 Service 的方式。

    • 使用者 Activity 与 Service 关系紧密,绑定在一起,通过 Binder 对象进行通信。
    • 绑定时如果服务没启动,则会执行初始化,但不会走 onStatCommand()。
    • 一个 Service 可以被多个使用者绑定。
    • 绑定 Service 和启动 Service 可以同时使用。
      • 举例:音乐播放器,可以通过Service在后台使用,开始播放 Start Service。在播放过程中要暂停、上一首、下一首等操作,使用 Bind Service 与其通信。
      • 同时使用兼具两者的特点,互相影响的地方是创建和销毁:没初始化时,只要有 Bind 或者 Create 就会初始化。Stop 不会导致 Binding 状态的服务销毁,同样 unbind 也不会导致已启动的服务销毁。
    • AIDL 用来定义复杂接口,实现跨进程的服务调用。

    代码套路

    生命周期

    // 绑定服务
    MyBindService()
    MyBindService.onCreate()
    MyBindService.onBind()
    ServiceConnection.onServiceConnected()
    // 解绑服务
    MyBindService.onUnbind()
    MyBindService.onDestroy()
    

    manifest 注册

    <service
        android:name=".services.MyService"
        android:enabled="true"
        android:exported="false" />
    

    代码

    1. 定义
    import android.app.Service;
    public class MyService extends Service {
    }
    
    1. 声明一个接口
    public interface MyIBinder {
        int calculate(int a, int b);
    }
    
    1. 创建一个Service的内部类继承 Binder 并实现这个接口
    public class MyBinder extends Binder implements MyIBinder {
        @Override
        public int calculate(int a, int b) {
            return MyService.this.calculate(a, b);
        }
    }
    
    1. onBind() 方法返回这个内部类的对象
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        return new MyBinder();
    }
    
    1. 在 Activity 中创建一个第 2 步的接口变量。
    private MyService.MyIBinder mServiceBinder;
    
    1. 在 Activity 中创建一个ServiceConnection 对象,在 onServiceConnected 方法中,将 IBinder 类型的参数转换为 MyIBinder 类型。
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("MyService", "onServiceConnected: ");
            mServiceBinder = (MyService.MyIBinder) service;
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("MyService", "onServiceDisconnected: ");
            mServiceBinder = null;
        }
    };
    
    1. 绑定 Bind
    private void doBind() {
        Intent intent = new Intent(this, MyService.class);
        if (bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) {
            shouldUnbind = true;
        } else {
            Log.e(TAG, "doBind: bind failed");
        }
    }
    
    1. 与 Service 通信
    @Override
    public void onClick(View v) {
        if (id == R.id.useService) {
            int result = mServiceBinder.calculate(10, 4);
        }
    }
    
    1. 解绑 Unbind
    private void doUnbind() {
        if (shouldUnbind) {
            unbindService(mConnection);
            shouldUnbind = false;
        }
    }
    
    1. 在 onDestroy 解绑
    @Override
    protected void onDestroy() {
        doUnbind();
        super.onDestroy();
    }
    

    其中第 5 步在 Activity 中创建一个 MyIBinder 接口对象,也可以直接将 Service 本身传递给 Activity。官方文档上的例子就是这么写的,更直接一点。

    异常和问题

    • 未绑定时不能调用 unbind 方法,会崩溃
      • java.lang.IllegalArgumentException: Service not registered
    • 内存泄漏,在 onDestroy() 中解绑
      • Activity MainActivity has leaked ServiceConnection MainActivity$1@4eb8a66 that was originally bound here

    相关文章

      网友评论

          本文标题:Android - Service Bind/Unbind 使用

          本文链接:https://www.haomeiwen.com/subject/wiqtbqtx.html