1.关键字的作用
in out inout 是 aidl中的 directional tag
,表示了在跨进程通信中数据的流向:
in 表示数据只能由
[客户端]
流向服务端,服务端会获取到客户端完整的数据,但客户端不会同步服务端你对该对象的修改,不写的话,默认的 tag 就是 inout 表示数据只能由
[服务端]
流向客户端,从服务端端接受该对象不为空,但字段内容为空,服务端修改对象后,binder 远程调用返回后,客户端会收到修改后的对象。inout 则表示数据可在服务端与客户端之间双向流通。
默认情况下,我们在 AIDL 中定义的接口方法是同步的,如果 AIDL 中的接口方法被 oneway 修饰了,那么这些方法就变成异步的了。
2.关键字解析
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable{
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
private String name;
private int price;
public Book(){}
public Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
/**
* 参数是一个Parcel,用它来存储与传输数据
* @param dest
*/
public void readFromParcel(Parcel dest) {
//注意,此处的读值顺序应当是和writeToParcel()方法中一致的
name = dest.readString();
price = dest.readInt();
}
//方便打印数据
@Override
public String toString() {
return "name : " + name + " , price : " + price;
}
}
Book.aidl 内容如下:
package com.yuandaima;
parcelable Book;
IHelloService.aidl
package com.yuandaima;
import com.yuandaima.Book;
interface IHelloService
{
int sayhelloin(in Book book);
int sayhelloout(out Book book);
int sayhelloinout(inout Book book);
oneway void sayhellooneway(in Book book);
}
我们来看下内部的 Proxy 类的实现:
private static class Proxy implements com.yuandaima.IHelloService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
//in 表示数据从客户端传递给服务端
@Override public int sayhelloin(com.yuandaima.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book!=null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0); //数据写入 Parcel 对象
}
else {
_data.writeInt(0);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_sayhelloin, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().sayhelloin(book);
}
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
//out 表示数据从服务端回传给客户端
@Override public int sayhelloout(com.yuandaima.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
//发送前不会向 Parcel 写入数据
try {
_data.writeInterfaceToken(DESCRIPTOR);
boolean _status = mRemote.transact(Stub.TRANSACTION_sayhelloout, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().sayhelloout(book);
}
_reply.readException();
_result = _reply.readInt();
if ((0!=_reply.readInt())) {
book.readFromParcel(_reply); //从返回数据中读出 book
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
// inout 表示数据从客户端传递给服务端,同时服务端也会传回客户端
@Override public int sayhelloinout(com.yuandaima.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book!=null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0); // 数据写入 Parcel 对象
}
else {
_data.writeInt(0);
}
boolean _status = mRemote.transact(Stub.TRANSACTION_sayhelloinout, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().sayhelloinout(book);
}
_reply.readException();
_result = _reply.readInt();
if ((0!=_reply.readInt())) {
book.readFromParcel(_reply); //从返回数据中读出 book
}
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
@Override public void sayhellooneway(com.yuandaima.Book book) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((book!=null)) {
_data.writeInt(1);
book.writeToParcel(_data, 0);
}
else {
_data.writeInt(0);
}
//发送数据时,最后一个参数是 FLAG_ONEWAY,表示调用是异步的
boolean _status = mRemote.transact(Stub.TRANSACTION_sayhellooneway, _data, null, android.os.IBinder.FLAG_ONEWAY);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().sayhellooneway(book);
return;
}
}
finally {
_data.recycle();
}
}
public static com.yuandaima.IHelloService sDefaultImpl;
}
接着我们在看先服务端 onTransact 中是如何处理数据的:
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
java.lang.String descriptor = DESCRIPTOR;
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(descriptor);
return true;
}
case TRANSACTION_sayhelloin:
{
data.enforceInterface(descriptor);
com.yuandaima.Book _arg0;
if ((0!=data.readInt())) {
//从 Parcel 中读出数据
_arg0 = com.yuandaima.Book.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
int _result = this.sayhelloin(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
case TRANSACTION_sayhelloout:
{
data.enforceInterface(descriptor);
com.yuandaima.Book _arg0;
_arg0 = new com.yuandaima.Book();
int _result = this.sayhelloout(_arg0);
reply.writeNoException();
reply.writeInt(_result);
if ((_arg0!=null)) {
reply.writeInt(1);
// 将数据写入需要返回的 Parcel 对象中
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_sayhelloinout:
{
data.enforceInterface(descriptor);
com.yuandaima.Book _arg0;
if ((0!=data.readInt())) {
//读取数据
_arg0 = com.yuandaima.Book.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
int _result = this.sayhelloinout(_arg0);
reply.writeNoException();
reply.writeInt(_result);
if ((_arg0!=null)) {
reply.writeInt(1);
//写入数据
_arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
else {
reply.writeInt(0);
}
return true;
}
case TRANSACTION_sayhellooneway:
{
data.enforceInterface(descriptor);
com.yuandaima.Book _arg0;
if ((0!=data.readInt())) {
_arg0 = com.yuandaima.Book.CREATOR.createFromParcel(data);
}
else {
_arg0 = null;
}
this.sayhellooneway(_arg0);
return true;
}
default:
{
return super.onTransact(code, data, reply, flags);
}
}
}
从源码我们可以看出,in out 的实现是通过是否从 Parcel 对象中读写数据实现的。oneway 是通过将 transact 方法最后一个参数设置为 FLAG_ONEWAY 实现的。