关于AIDL一些需要注意的地方

来源:互联网 发布:瑞士军刀男 知乎 编辑:程序博客网 时间:2024/05/16 18:12

参考:sdk-22.3/docs/guide/components/aidl.html

1、从远程客户端进程来的调用是由不同的线程发起的,运行在不同的进程。所以,服务端必须处理好在同一时刻有多个从不同线程过来的请求的情况。也就是说,一个AIDL的实现必须是完成线程安全的,必须手动处理多线程的情况。

2、AIDL接口当中的oneway关键字代表远程调用的行为。当使用的时候,远程调用不会阻塞,会立即返回。


AIDL中支持的类型:

1、所有的Java基本数据类型,比如int,long,boolean,char,float等。

2、String

3、CharSequence

4、List,List当中的数据元素必须能够被AIDL支持

5、Map:只支持HashMap,里面的每个元素都必须被AIDL支持,包括key和value

6、Parcelable:实现了Parcelable接口的对象

7、AIDL接口:所有的AIDL接口本身也可以在AIDL文件中使用。


其中自定义的Parcelable对象和AIDL对象必须要显式的import进来,不管这些对象是否和当前的AIDL是否是在同一个包中。如下所示,IRemoteService和IRemoteServiceCallback在同一个包当中。


然后在IRemoteService 当中使用了IRemoteServiceCallback接口,就需要把IRemoteServiceCallback  import进来,不然会报错,代码如下所示:

/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.easyliu.demo.aidl;import com.easyliu.demo.aidl.IRemoteServiceCallback;/** * Example of defining an interface for calling on to a remote service * (running in another process). */interface IRemoteService {    /**     * Often you want to allow a service to call back to its clients.     * This shows how to do so, by registering a callback interface with     * the service.     */    void registerCallback(IRemoteServiceCallback cb);        /**     * Remove a previously registered callback interface.     */    void unregisterCallback(IRemoteServiceCallback cb);}

当定义服务AIDL接口的时候,有几点需要注意

1、方法可能有零个或者多个输入参数,可以返回一个值或返回空

2、AIDL中除了基本数据类型参数,其他类型的参数必须标上方向:in、out或者inout。基本类型默认就是in,不能是其他。

3、AIDL文件当中的注释将会包括在产生的.java文件当中,除了在import和包名前面的注释。

4、AIDL中只支持方法,不支持静态常量。


通过IPC传递对象

如果你有一个类需要跨进程进行传输,你必须保证这个类实现了Parcelable接口并且在IPC的另外一端也有这个类。

为了创建一个支持Parcelable协议的类,必须做下面工作:

1、保证你的类实现Parcelable接口

2、实现writeToParcel方法,这个方法将得到当前对象的状态,然后写入Parcel

3、给类增加一个叫做CREATOR的静态常量,这个静态常量实现了Parcelable.Creator接口

AIDL使用以上这些方法和域实现对象的序列化和反序列化

4、最后,如果在AIDL中用到了这个自定义的类,那么必须创建一个和它同名的.aidl文件,并在其中这个类为Parcelable类型,如下所示,创建了一个Rect.aidl文件,在这个文件中声明了Rect为Parcelable类型。

// Rect.aidlpackage com.easyliu.demo.aidlremotedemo;parcelable Rect;

下面是Rect类的具体实现:

package com.easyliu.demo.aidlremotedemo;/** * Created by LiuYi on 2016/6/19. */import android.os.Parcel;import android.os.Parcelable;public final class Rect implements Parcelable {    public int left;    public int top;    public int right;    public int bottom;    public static final Parcelable.Creator<Rect> CREATOR = new            Parcelable.Creator<Rect>() {                public Rect createFromParcel(Parcel in) {                    return new Rect(in);                }                public Rect[] newArray(int size) {                    return new Rect[size];                }            };    private Rect(Parcel in) {        readFromParcel(in);    }    public void readFromParcel(Parcel in) {        left = in.readInt();        top = in.readInt();        right = in.readInt();        bottom = in.readInt();    }    @Override    public int describeContents() {        return 0;    }    @Override    public void writeToParcel(Parcel dest, int flags) {        dest.writeInt(left);        dest.writeInt(top);        dest.writeInt(right);        dest.writeInt(bottom);    }}


使用Rect的方式如下所示:有一个AIDL接口IRectManager,里面使用了Rect对象,需要把Rect给import进来,在addRect方法的参数中,标注了参数的方向:in。

// IRectManager.aidlpackage com.easyliu.demo.aidlremotedemo;import com.easyliu.demo.aidlremotedemo.Rect;interface IRectManager {   List<Rect> getRectList();   void addRect(in Rect rect);}


最好是把AIDL相关的类和文件都放到一个包里面,这样就可以直接在客户端和服务端进行移植,如下所示:




1 0
原创粉丝点击