Android Service--通信方式(IBinder回调、Messenger)

Activity与Service的通信,分两大类,同一个进程中、不同的进程中。

同一个进程中

可以通过直接实现IBinder接口,或者继承Binder类。Binder类是系统提供的一个IBinder接口的实现类。

Service中:

  public class MyBind extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }

在onBind的时候返回MyBind

@Override
    public IBinder onBind(Intent intent) {
        super.onBind(intent);
        return new MyBind();
    }

Activity中:
bindService的时候在ServiceConnection的回调中得到MyService对象

    conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                isBind = true;
                if (service instanceof MyService.MyBind){
                     myService = ((MyService.MyBind) service).getService();
                }
                Log.i("life", "ServiceConnection-----onServiceConnected");
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                isBind = false;
                Log.i("life", "ServiceConnection----onServiceDisconnected");
            }
        };

这样就在activity中的到了Service的对象。就可以随意调用Service提供的方法了。

不同的进程中

Messenger方式
Messenger需要结合Handler一起使用。有send方法,最终调用的是handler方法。

Service中:

	private MyHandler handler;
    private Messenger messenger;

    @Override
    public void onCreate() {
        super.onCreate();
        handler = new MyHandler();
        messenger=new Messenger(handler);
    }

....
 public static class MyHandler extends Handler {
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            Log.i("life", "MyHandler----dispatchMessage");
            Log.i("life", Thread.currentThread().getName());
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.i("life", "MyHandler----handleMessage");
        }
    }

需要一个handler,一个Messenger对象。handler最终会负责发送和接收消息。我们就可以在MyHandler中处理Activity发来的各种消息了。

Activity中:

conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                isBind = true;
                messenger = new Messenger(service);
                Log.i("life", "ServiceConnection-----onServiceConnected");
                Log.i("life", Thread.currentThread().getName());
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                isBind = false;
                Log.i("life", "ServiceConnection----onServiceDisconnected");
            }
        };
        
....
//点击发送
Message message = Message.obtain();
message.what = 5;
try {
	messenger.send(message);
} catch (RemoteException e) {
	e.printStackTrace();
}

这样就完成了通过Messenger夸进程传递内容了。

Messenger源码浅析:

public final class Messenger implements Parcelable {
    private final IMessenger mTarget;

    /**
     *构造方法需要一个handler对象
     *@param target 将接收发送的消息
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
    
     /**
     * @return 返回当前Messenger的IBinder对象
     */
    public IBinder getBinder() {
    	//其实也是封装了AIDL
        return mTarget.asBinder();
    }
    
    /**
     *构造方法了
     * @param target 需要传入之前通过getBinder()的到的IBinder
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
    
    /**
     *发送消息
     *如果handler已经不存在了,抛异常
     */
    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }

上面四个方法就是我们调用的,前面两个方法在Service中调用。后两个方法在Activity中调用。
类中有一个对象 private final IMessenger mTarget,在传入Handler对象的时候进行的实例化。
看下handler.getIMessenger();

....
	final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }
....
    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            msg.sendingUid = Binder.getCallingUid();
            Handler.this.sendMessage(msg);
        }
    }

可以看到IMessenger 的对象来自handler的内部类MessengerImpl 。而这个类其实是继承了一个AIDL生成的类,AIDL提供了一个send(Message msg) 方法。并且还给这个msg赋值了sendingUid,也就是当前启动Service的应用ID,最终通过handler发送msg。
这样Looper就可以知道这个消息所在的应用和所对应的handler。在列子中,所在的线程在Service的主线程中,而一个线程只有一个Looper

双向通信

上面利用Messenger实现了Activity向Service夸进程发送消息。那如何来实现,Service像Activity发送消息呢。
当然还是要利用Messenger,那么如何传递一个Messenger对象到Service呢,Activity中可没有对应的回调。
来看代码:
Activity中:

//处理接收消息的handler。
public class ActivityHandler extends Handler {
        @Override
        public void dispatchMessage(Message msg) {
            super.dispatchMessage(msg);
            Log.i("life", "ActivityHandler----dispatchMessage");
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.i("life", "ActivityHandler----handleMessage");
            bt2.setText("service来消息啦");
        }
    }
......
	/**
     * Activity中的Messenger对象
     */
    private Messenger activityMessenger;
    /**
     * Activity中接收消息的handler
     */
    private ActivityHandler handler;
 	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_service);
        ButterKnife.bind(this);
        ....
        handler = new ActivityHandler();
        activityMessenger = new Messenger(handler);
    }

上面代码完成了Messenger和Handler对象的创建,接下来,把Messenger传递到Service中。

			...
 			case R.id.bt_1:
                Message message = Message.obtain();
                message.what = 5;
                //将Activity中的Messenger对象,交给message对象
                message.replyTo = activityMessenger;
                try {
                	//向Service发送消息
                    serviceMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
                ...

Meesage类的变量replyTo就是一个Messenger对象
public final class Message implements Parcelable {
.....
    /**
     * Optional Messenger where replies to this message can be sent.  The
     * semantics of exactly how this is used are up to the sender and
     * receiver.
     */
    public Messenger replyTo;
.....
}

通过上面的代码,把Activity中的Messenger对象,交给了发送过去的Message对象。
Service中的接收并向Activity中发送

 		@Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.i("life", "MyHandler----handleMessage");
            //取出Activity中传递过来的Messenger对象,并发送消息
            Messenger activityMessenger=msg.replyTo;
            try {
            	msg=Message.obtain();
                activityMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

上面的代码在Service中完成了接收,和反馈消息。

总结:

  • 同一个进程中,可以使用IBinder子类回调。当然也可以用Messenger。这个时候的Activity和Service运行在同一个线程中。
  • 不同进程,IBinder子类回调不在支持,Messenger是一种方式。这个时候的Activity和Service运行在不同的线程中。
  • 其实Messenger内部实现也是AIDL。

Messenger步骤:

  1. 利用需要handler作为参数的构造方法实例化Messenger对象。
  2. 把Messenger通过某种方式回调到,消息发送方。
    比如:文章中Service中使用onBind回调到Activity中;Activity利用发送的Message来携带到Service中。
  3. 调用Messenger的send方法发送消息。
  4. handler处理消息。

进程之间的内存资源是独立的,那么message对象和Messenger对象,为啥可以传递呢?
没错就是序列化和反序列化。这样传输的数据就转化为能够在内存之间流通的形式了,也就是IO流操作了。Message和Messenger这两个类都是实现了Parcelable接口的。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值