Android进程间通信AIDL的in、out、inout三种定向tag的使用

AIDL定义

AIDL,全称Android Interface Definition Language,即Android接口定义语言。Android的一种进程间通信方式,同时也是Binder和Messager的底层。
在很多介绍aidl的文章中,都可以发现有三种定向tag:in、out、inout的使用,它们一般用于修饰aidl文件中的非基本类型参数。那么它们都是做什么用的呢?
经过本人一阵摸索,掌握了一些规律,分享出来,供大家参考~
- in: 默认方式;客户端将参数传给服务端使用,如同子弹,打出去就不管了~
- out:客户端将一个参数传给服务端,服务端将其作为容器,丢弃其中所有属性值后,再填充内容,然后还给客户端继续处理;如同一个盘子,服务端装满食物后,由客户端使用~
- inout:客户端将参数传给服务器,服务端可以使用参数的值,同时对这个参数进行修改,客户端会得到修改后的参数,如果是集合数组等,可修改其内部的子对象;如同客户端传给服务端一本书,服务端可以查看书中内容,也可以做一些笔记,然后还给客户端。
下面用代码演示~
1、首先看AIDL文件:

 // IBookManager.aidl
package com.example.wang.client.aidl;

import com.example.wang.client.bean.OrderBean;

interface IOrderManager {
    List<OrderBean> getAll();
    void add(in OrderBean bean);
    void getNameList(out String[] names);
    void updateIdList(inout String[] ids);
    void getOrder(out OrderBean bean);
    void updateOrder(inout OrderBean bean);
}
// OrderBean.aidl
package com.example.wang.client.bean;
parcelable OrderBean;

2、OrderBean类

package com.example.wang.client.bean;
...
public class OrderBean implements Parcelable{
    private String id;
    private String name;
    private int amount;

    public OrderBean(){}

    public OrderBean(String id, String name, int amount) {
        this.id = id;
        this.name = name;
        this.amount = amount;
    }

    protected OrderBean(Parcel in) {
        id = in.readString();
        name = in.readString();
        amount = in.readInt();
    }

    public static final Creator<OrderBean> CREATOR = new Creator<OrderBean>() {
        @Override
        public OrderBean createFromParcel(Parcel in) {
            return new OrderBean(in);
        }

        @Override
        public OrderBean[] newArray(int size) {
            return new OrderBean[size];
        }
    };

    //省略get/set方法

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(id);
        dest.writeString(name);
        dest.writeInt(amount);
    }
    public void readFromParcel(Parcel in){
        id = in.readString();
        name = in.readString();
        amount = in.readInt();
    }

    @Override
    public String toString() {
        String string = "OrderBean{id:"+id+",name:"+name+",amount:"+amount+"}";
        return string;
    }
}

3、客户端绑定代码

//MainActivity.java
package com.example.wang.client;
...

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private List<OrderBean> orderList;
    private IOrderManager orderManager;
    //UI细节省略
    ...
    //连接远程service
    ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            IOrderManager manager = IOrderManager.Stub.asInterface(service);
            orderManager = manager;
            refreshOrderList();
            ...
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //UI相关代码略过
        ...
        //bind
        bindOrderService();
    }
    private void bindOrderService(){
        Intent intent = new Intent("com.example.wang.ordermanager.OrderService");
        intent.setPackage("com.example.wang.ordermanager");
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }

    @Override
    public void onClick(View v) {
        if(v==search_button){
            //重点看这里
            try {
                //测试out方式,传递数组
                String[] names={"老虎","狮子","大象","骆驼"};
                orderManager.getNameList(names);
                Log.i("MainActivity","@@ 刷新订单 names="+ Arrays.toString(names));
                //测试inout方式,传递数组
                String[] ids={"a1","b2","c3","b4"};
                orderManager.updateIdList(ids);
                Log.i("MainActivity","@@ 刷新订单 ids="+ Arrays.toString(ids));
                //测试out方式,传递Parcelable对象
                OrderBean order1=new OrderBean("123","降龙十八掌",3456);
                orderManager.getOrder(order1);
                Log.i("MainActivity","@@ 刷新订单 order1 -> "+order1.toString());
                //测试inout方式,传递Parcelable对象
                OrderBean order2=new OrderBean("456","独孤九剑",6789);
                orderManager.updateOrder(order2);
                Log.i("MainActivity","@@ 刷新订单 order2 -> "+order2.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            refreshOrderList();
        }else if(v==add_button){
            //增加订单,使用in方式
            try {
                OrderBean orderBean=new OrderBean();
                Random random=new Random();
                orderBean.setAmount(random.nextInt(800)+100);
                orderBean.setId(random.nextInt(100000000)+100000+"");
                orderBean.setName("玩具"+random.nextInt());
                orderManager.add(orderBean);
                refreshOrderList();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
}

4、服务端service代码:

//OrderService.java
package com.example.wang.ordermanager;
...
public class OrderService extends Service{
    private CopyOnWriteArrayList<OrderBean> list = new CopyOnWriteArrayList<>();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.i("OrderService","@@ onBind");
        return binder;
    }

    Binder binder = new IOrderManager.Stub(){

        @Override
        public List<OrderBean> getAll() throws RemoteException {
            return list;
        }

        @Override
        public void add(OrderBean bean) throws RemoteException {
            bean.setId(bean.getId()+"_ii");
            bean.setName(bean.getName()+"_nn");
            bean.setAmount(bean.getAmount()+50000);
            Log.i("OrderService","@@ add bean="+ bean.toString());
            list.add(bean);
        }

        @Override
        public void getNameList(String[] names) throws RemoteException {
            Log.i("OrderService","@@ getNameList names="+ Arrays.toString(names));
            names[0]="苹果";
            names[1]="香蕉";
            names[2]="榴莲";
        }

        @Override
        public void updateIdList(String[] ids) throws RemoteException {
            Log.i("OrderService","@@ setIdList names="+ Arrays.toString(ids));
            ids[0]=ids[0]+"_11";
            ids[1]=ids[1]+"_22";
            ids[2]=ids[2]+"_33";
        }

        @Override
        public void getOrder(OrderBean bean) throws RemoteException {
            Log.i("OrderService","@@ updatePrice "+bean.toString());
            bean.setId(bean.getId()+"-12345");
            bean.setName(bean.getName()+"-九阴真经");
            bean.setAmount(bean.getAmount()+10000);
        }

        @Override
        public void updateOrder(OrderBean bean) throws RemoteException {
            Log.i("OrderService","@@ updateOrder id="+bean.toString());
            bean.setId(bean.getId()+"-98765");
            bean.setName(bean.getName()+"-葵花宝典");
            bean.setAmount(bean.getAmount()+20000);
        }
    };
}

5、查看输出结果:

//in方式
04-16 17:24:01.648 31198-31229/com.example.wang.ordermanager I/OrderService: @@ add bean=OrderBean{id:43788467_ii,name:玩具1186168941_nn,amount:50731}
04-16 17:24:01.649 31279-31279/com.example.wang.client I/MainActivity: @@ 增加订单 order1 -> OrderBean{id:43788467,name:玩具1186168941,amount:731}
//out方式,数组参数
04-16 17:24:05.602 31198-31211/com.example.wang.ordermanager I/OrderService: @@ getNameList names=[null, null, null, null]
04-16 17:24:05.603 31279-31279/com.example.wang.client I/MainActivity: @@ 刷新订单 names=[苹果, 香蕉, 榴莲, null]
//inout方式,数组参数
04-16 17:24:05.611 31198-31229/com.example.wang.ordermanager I/OrderService: @@ setIdList names=[a1, b2, c3, b4]
04-16 17:24:05.612 31279-31279/com.example.wang.client I/MainActivity: @@ 刷新订单 ids=[a1_11, b2_22, c3_33, b4]
//out方式,Parcelable参数
04-16 17:24:05.613 31198-31210/com.example.wang.ordermanager I/OrderService: @@ updatePrice OrderBean{id:null,name:null,amount:0}
04-16 17:24:05.614 31279-31279/com.example.wang.client I/MainActivity: @@ 刷新订单 order1 -> OrderBean{id:null-12345,name:null-九阴真经,amount:10000}
//inout方式,Parcelable参数
04-16 17:24:05.615 31198-31211/com.example.wang.ordermanager I/OrderService: @@ updateOrder id=OrderBean{id:456,name:独孤九剑,amount:6789}
04-16 17:24:05.616 31279-31279/com.example.wang.client I/MainActivity: @@ 刷新订单 order2 -> OrderBean{id:456-98765,name:独孤九剑-葵花宝典,amount:26789}

通过输出结果可以发现:
1. 使用in方式时,参数值单向传输,客户端将对象传给服务端后,依然使用自己的对象值,不受服务端的影响。
2. 使用out方式传递数组类型时,客户端传递给服务端的只有数组的长度,客户端得到的是服务端赋值后的新数组。
3. 使用inout方式传递数组类型时,客户端会将完整的数组传给服务端,客户端得到的是服务端修改后的数组。
4. 使用out方式传递Parcelable对象时,客户端传给服务端的是一个属性值全部为空的对象,得到的是服务端重新赋值后的对象。
5. 使用inout方式传递Parcelable对象时,客户端会将完整的对象传递给服务端,得到的是服务端修改后的对象。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页