你真的理解AIDL中的in,out,inout么?

前言

这其实是一个很小的知识点,大部分人在使用AIDL的过程中也基本没有因为这个出现过错误,正因为它小,所以在大部分的网上关于AIDL的文章中,它都被忽视了——或者并没有,但所占篇幅甚小,且基本上都是官方文档的译文,译者读者其实都不知其然。这几天在研究AIDL,偏偏我又是个执拗的性子,遇着不清不楚的东西就是想把它捋清楚,就下了些功夫研究了下AIDL中的定向tag,研究了下它的 in , out , inout 。

整理而成此博文。

正文

1,概述

首先要说的是定向tag是AIDL语法的一部分,而 in , out , inout 是三个定向tag,所以读者要有一定的对于Android中AIDL的了解,关于AIDL相关的知识大家可以参考这篇博文:Android:学习AIDL,这一篇文章就够了(上) 。 另外,这篇文章基本上可以说是我研究这个东西的心路历程,可能会有些絮叨,请各位看官见谅。

2,官方文档

Android官网上在讲到AIDL的地方关于定向tag是这样介绍的:

All non-primitive parameters require a directional tag indicating which way the data goes . Either in , out , or inout . Primitives are in by default , and connot be otherwise .

直译过来就是:所有的非基本参数都需要一个定向tag来指出数据流通的方式,不管是 in , out , 还是 inout 。基本参数的定向tag默认是并且只能是 in 。对于这个定向tag我的心里是有一些疑问的。首先,数据流通的方式是指什么?其次, in , out , inout 分别代表了什么,它们有什么区别?很显然,官方文档并没有把这些东西交代清楚。那么接下来我就只能自己把这些问题搞清楚了。

本着不重复造轮子的原则,我首先在 Google 上查找了一下这方面的资料,看能不能有比较好的答案,结果确实找到了一些说法——但是进过论证,似乎都有一些漏洞。所以没办法,只能自己开始着手研究它是怎么回事了。

3,开始研究

3.1,输入输出?NO!

首先第一个跑到我脑海里的猜测就是:in表示输入,也即方法的传参,out表示输出,也即方法的返回值。有这样的猜测很合情合理,但是这样的猜测很不合情合理。原因如下:

  • 文档里说了,基本参数的定向tag默认且只能是 in ,但是很显然,基本参数既有可能是方法的传参,也有可能是方法的返回值,所以这个猜测本身就站不住脚。
  • 如果 in 表示输入, out 表示输出,那 inout 应该表示什么?
  • 进过实测,定向tag只能用来修饰AIDL中方法的输入参数,并不能修饰其返回值。

综合以上几点考虑,基本可以排除这种猜测的可能性。

3.2,way?way!

排除掉上面的想法后,我开始进一步猜测 in , out ,inout 可能代表的意义——在某一个瞬间我灵光一闪:除了输入输出,in ,out 还总是被用来表示数据的流向!同时我惊觉,似乎我对官方文档的理解有一些偏差:way有方法的意思,但是它也有道路的意思!如果按照道路理解,那么官网的译文就应当是:所有的非基本参数都需要一个定向tag来指出数据的流向,不管是 in , out , 还是 inout 。基本参数的定向tag默认是并且只能是 in 。

如果按照这个意思的话,似乎它们的含义就很清晰了:in 与 out 分别表示客户端与服务端之间的两条单向的数据流向,而 inout 则表示两端可双向流通数据。基于这种猜测,我设计了一个实验来验证它,AIDL文件是这样的:

// Book.aidl
package com.lypeer.ipcclient;

parcelable Book;
// BookManager.aidl
package com.lypeer.ipcclient;
import com.lypeer.ipcclient.Book;

interface BookManager {    
    //保证客户端与服务端是连接上的且数据传输正常
    List<Book> getBooks();

    //通过三种定位tag做对比试验,观察输出的结果
    Book addBookIn(in Book book);
    Book addBookOut(out Book book);
    Book addBookInout(inout Book book);
}

对其中的AIDL的语法不熟悉的,可以再去温故一下:Android:学习AIDL,这一篇文章就够了(上) ,我这里就不赘叙了。我主要讲一下实验的思路。可以看到,有定位tag的那三个方法它们的传参和返回值都是 Book 对象(Book是我自定义的一个实现了Parcelable的类,里面只有两个参数,String nameint price),并且它们的定位tag都不一样,接下来我会在客户端调用这三个方法,然后分别在客户端和服务端打印相关信息,从而验证我的猜想。下面贴上客户端和服务端的代码:

/**
 * 客户端的AIDLActivity.java
 * 由于测试机的无用debug信息太多,故log都是用的e
 *
 * Created by lypeer on 2016/7/17.
 */
public class AIDLActivity extends AppCompatActivity {
   

    //由AIDL文件生成的Java类
    private BookManager mBookManager = null;

    //标志当前与服务端连接状况的布尔值,false为未连接,true为连接中
    private boolean mBound = false;

    //包含Book对象的list
    private List<Book> mBooks;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_aidl);
    }

    /**
     * 按钮的点击事件,点击之后调用服务端的addBookIn方法
     *
     * @param view
     */
    public void addBookIn(View view) {
        //如果与服务端的连接处于未连接状态,则尝试连接
        if (!mBound) {
            attemptToBindService();
            Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
            return;
        }
        if (mBookManager == null) return;

        Book book = new Book();
        book.setName("APP研发录In");
        book.setPrice(30);
        try {
            //获得服务端执行方法的返回值,并打印输出
            Book returnBook = mBookManager.addBookIn(book);
            Log.e(getLocalClassName(), returnBook.toString());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    public void addBookOut(View view) {
        if (!mBound) {
            attemptToBindService();
            Toast.makeText(this, "当前与服务端处于未连接状态,正在尝试重连,请稍后再试", Toast.LENGTH_SHORT).show();
            return;
        }
        if (mBookManager == null) return;

        Book book = new Book();
        book.setName("APP研发录Out");
        book.setPrice(30);
        try {
            Book returnBook = mBookManager.addBookOut(book);
            Log.e(getLocalClassName(), returnBook.toString());
        } catch (RemoteException e) {
            e.printStackTrace();
      
  • 76
    点赞
  • 145
    收藏
    觉得还不错? 一键收藏
  • 50
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值