温故知新之进程间通讯技术(IPC)

端午节假期 第一天,闲下来整理下一直想总结的东西。

今天说的是进程间通讯。

1.应用场景:在android中应用是以进程的形式存在的,而在android中是不允许跨进程内存共享数据的,那如何在进程间传递对象呢?在此背景下,进程间通讯技术诞生了——Binder机制,基于此基础之上提供了整体的封装,从而实现对象代理机制。

2.aidl介绍:android接口定义语言。aidl支持的数据类型:java原子类型,Binder引用以及实现了Parcelable接口的对象。

      新建一个aidl文件后(这里以ITestService为例),adt会在项目的gen目录下自动生成java文件。其主要完成:一是定义java interface,内部包含aidl文件所声明的服务函数,该类基于IInterface接口,即需要提供一个asBinder函数;二则定义一个proxy类,该类将作为客户端远程访问服务端的代理;最后则是定义一个stub类,其是基于Binder的抽象类

@Override
 public android.os.IBinder asBinder()
{
return this;
}
private static class Proxy implements com.demo.ITestService
{//aidl接口中定义的各种方法
}
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}


3.通讯:在这里我们称互相通信的进程双方为客户端和服务端

(1).客户端初始化与服务端之间的连接获取服务端代理对象

/*
* 初始化客户端和服务器端的连接
*/
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 从远程service中获得AIDL实例化对象
tService = ITestService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("TAG", "disconnect");
tService = null;
}
};


(2).客户端通过调用服务器代理对象的方法向服务器端发送请求。

@Override
public void login(final String userName, final String passWord) {
new Thread(new Runnable() {
@Override
public void run() {
try {
new Thread(new Runnable() {
@Override
public void run() {
try {
if (tService == null) {
Log.e("TAG", "tServicenull");
}
tService.login(userName, passWord);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
}



(3).代理对象把用户请求通过Linux内核的Binder驱动发送到服务端进程,服务端进程处理用户请求,并通过Linux内核的Binder驱动返回结果给客户端的服务器代理对象。

private ITestService.Stub binder = new com.demo.ITestService.Stub() {
@Override
public void login(final String name,
final String password) throws RemoteException {
//服务端登陆逻辑判断
}
}
/**
登录回调
*/
@Override
public void onLoginResult(Message message) throws RemoteException {
handler.post(new Runnable() {
@Override
public void run() {
synchronized (locker) {
//登录结果处理
}
});
}


备注:1.客户端与服务端的绑定方式

(一)、startService启动服务,会调用如下生命周期方法:

   onCreate—>onStart—>onDestory()

(二)、bindService启动服务,会调用如下生命周期方法: 

                                onCreate—>onBind—>onUnbind—>onDestory()
两者的不同点:使用startService()方法启用,访问者与服务之间没有关联,即使访问者退出了,服务仍然运行,使用bindService()方法启用服务,访问者与服务绑定在一起,访问者一旦退出,服务也就终止

例如:final Intent service = new Intent(ITestService.class.getName());

                        this.app.bindService(service, connection, Context.BIND_AUTO_CREATE);

  2.服务端将登陆结果如何返回给客户端中自己的代理?

这里用到了进程间通讯中的RemoteCallbackList回调技术。

客户端:

 

  //初始化服务端回调
 ITestServiceCallBack callBack = new  ITestServiceCallBack.Stub() {
//各种回调方法,如上面的public void onLoginResult(Message message){}
 }
//服务端代理注册监听
tService.registerListeners(callBack);

服务端:在实现自己的各种方法的同时给客户端提供回调监听接口

private ITestService.Stub binder = new com.demo.ITestService.Stub() {
@Override
public void login(final String name,
final String password) throws RemoteException {
//服务端登陆逻辑判断
}
/**
* 注册回调监听
*/
@Override
public void registerListeners(ITestServiceCallBack callback)
throws RemoteException {
listeners.register(callback);
};
/**
* 销毁回调监听
*/
@Override
public void unRegisterListener(ITestServiceCallBack callback)
throws RemoteException {
listeners.unregister(callback);
}

登录逻辑判断完成后,广播发送消息

int n = listeners.beginBroadcast();
for (int i = 0; i < n; i++) {
ITestServiceCallBack listener = listeners
.getBroadcastItem(i);
listener.onLoginResult(message);
}


3.客户端终止与服务端连接

app.stopService(new Intent(app.getApplicationContext(),
TestService.class)); 

该知识点整理完毕,后续有新感悟会陆续修正,完善。端午节快乐~


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值