美文网首页
AIDL 关键字 in out inout oneway 解析

AIDL 关键字 in out inout oneway 解析

作者: 竖起大拇指 | 来源:发表于2024-05-08 18:15 被阅读0次

1.关键字的作用

in out inout 是 aidl中的 directional tag,表示了在跨进程通信中数据的流向:

  • in 表示数据只能由[客户端]流向服务端,服务端会获取到客户端完整的数据,但客户端不会同步服务端你对该对象的修改,不写的话,默认的 tag 就是 in

  • out 表示数据只能由[服务端]流向客户端,从服务端端接受该对象不为空,但字段内容为空,服务端修改对象后,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 实现的。

相关文章

  • AIDL要点总结

    1.in、out、inout、oneway关键字 定向tag in修饰的的参数,经序列化后传递服务端,服务端反序列...

  • Android Aidl使用 In Out InOut分析

    Android Aidl使用 In Out InOut分析 1.Aidl作用 AIDL是一个缩写,全称是Andro...

  • AIDL in out inout

    点击原文 @CSDN lypeer 补充 in out 仅仅指数据流向,和客户端服务端无关,如果服务端主动调用客户...

  • AIDL源码解析in、out和inout

    个人博客地址 http://dandanlove.com/ 为什么会想写这篇文章,只因为一个error idl.e...

  • AIDL中的in out inout

    AIDL中的in out inout,官方是这样介绍的, All non-primitive parameters...

  • AIDL 之 in, out, inout

    遇到问题,更新API的时候:NotificationManager.aidl:38.76-84: The dire...

  • AIDL中的in,out,inout源码解析

    前言 最近研究Android系统源码,难免接触到很多aidl接口。突然发现自己总是将in,out,inout这几个...

  • Binder

    AIDL1.流向 in作为定向 tag 表示数据变更只能由调用方流向接收方,out 反之,inout 则为数据可以...

  • AIDL oneway

    原文地址:https://mp.weixin.qq.com/s/Jc2mrxeMVTJXudoPx5K4-w on...

  • 「Android Binder」AIDL中的 in / out

    用过aidl的同学,可能见过下面的写法: 不知道你有没有好奇过这里的 in / out / inout 是什么意思...

网友评论

      本文标题:AIDL 关键字 in out inout oneway 解析

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