Android AIDL使用之Parcelable对象

安卓AIDL通信中自定义Parcelable对象使用
Views: 500
0 0
Read Time:2 Minute, 12 Second

parcel是安卓binder通信中的消息载体,通过IBinder进行传递。Parcel的源码实现为android.os.Parcel,继承自java.lang.object。涉及的相关源码为:

base/core/java/android/os/Parcel.java  //java 实现
frameworks/base/core/jni/android_os_Parcel.cpp //JNI实现
frameworks/native/libs/binder/Parcel.cpp // C++实现
frameworks/native/libs/binder/include/binder/Parcelable.h  //c++ 头文件

有些时候我们需要在binder中传递自定义的数据类型或者类,此时需要使该类实现Parcelable接口,如果我们是在C++程序与Java程序中进行传递,那么C++与Java侧都需要实现Parcelable接口。支持Parcelbale接口十分重要,Android系统可通过该接口将对象分解成各进程支持的原生类型。这里需要注意的是,Parcel是实体类,而Parcelable是接口。

自己实现Parcelable接口,根据后端语言的不同,具体实现上也存在差异。这里将分别以Java和C++两种后端语言给出示例。

Java

1.定义aidl文件,如myParcelable.aidl,这里其实有约定俗成的命名方式,不需要像定义接口那样以I开头,并且其内容如下:

package android.com.example;
parcelable myParcelable;

2.实现Parcelable接口中的int describeContents()、void writeToParcel(Parcel dest,int flags)以及为myParcelable类添加CREATOR静态字段,实现Parcelable.Creator接口的对象,这里给出示例代码:

import android.os.Parcel;
import android.os.Parcelable;

public final class myParcelable implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;
    //实现Parcelable.Creator的接口
    public static final Parcelable.Creator<myParcelable> CREATOR = new 
    Parcelable.Creator<myParcelable>() {
        public myParcelable createFromParcel(Parcel in) {
            return new myParcelable(in);
        }

        public myParcelable[] newArray(int size) {
            return new myParcelable[size];
        }
    };

    public myParcelable() {
    }

    private myParcelable(Parcel in) {
        readFromParcel(in);
}

    public void readFromParcel(Parcel in) {
        left = in.readInt();
        top = in.readInt();
        right = in.readInt();
        bottom = in.readInt();
    }
   //实现Parcelable接口 
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(left);
        out.writeInt(top);
        out.writeInt(right);
        out.writeInt(bottom);
    }
    public int describeContents() {
        return 0;
}

在使用时导入相应的Parcelable类即可。

C++

使用C++来实现Parcelable类相比于Java实现要复杂许多,大致包含如下几个步骤。

1.定义aidl文件,如myParcelable.aidl,其内容如下:

package android.com.example;
parcelable myParcelable cpp_header “myParcelable.h”;

2.添加对应的头文件与源码文件,如myParcelable.h与myParcelable.cpp,在头文件中声明类myParcelable并使其继承android::Parcelable,覆写virtual status_t writeToParcel(Parcel* parcel)与virtual status_t readFromParcel(const Parcel* parcel),并根据自身需要实现其他的方法即可,这里给出示例代码。

myParcelable.h头文件:

//myParcelable.h
#ifndef __MY_PARCELABLE_H__
#define __MY_PARCELABLE_H__

#include <vector>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <binder/Parcelable.h>
#include <binder/Parcel.h>


using namespace std;
using android::Parcel;
using android::Parcelable;
using android::String16;
using android::String8;


class myPaecelable : public Parcelable
{
public:
  myPaecelable ();
  myPaecelable (int32_t messageId);
  ~myPaecelable ();
  virtual status_t writeToParcel(Parcel *parcel) const override;
  virtual status_t readFromParcel(const Parcel *parcel) override;
  void setMessageId(const int32_t messageId);

public:
  int32_t messageId;
};
#endif

myParcelable.cpp源文件

include "myParcelable.h"

myPaecelable ::myPaecelable () : messageId(0)
{
}

myPaecelable ::~myPaecelable ()
{
}

myPaecelable ::myPaecelable (int32_t messageId) : messageId(messageId)
{
}

status_t myPaecelable ::writeToParcel(Parcel *parcel) const
{
    if (parcel == nullptr)
    {
        LOGE("[myPaecelable ] parcel == nullptr");
        return BAD_VALUE;
    }
    status_t res = OK;
    res = parcel->writeInt32(messageId);
    if (res != OK)
    {
        LOGE("[myPaecelable ] writeInt32 failed, ret:[%d]", res);
        return res;
    }
    return OK;
}

status_t myPaecelable ::readFromParcel(const Parcel *parcel)
{
    if (parcel == nullptr)
    {
        LOGE("[myPaecelable] parcel == nullptr");
        return BAD_VALUE;
    }
    status_t res = OK;
    res = parcel->readInt32(&messageId);
    if (res != OK)
    {
        LOGE("[myPaecelable] readInt32 failed, ret:[%d]", res);
        return res;
    }
    return OK;
}

void myPaecelable ::setMessageId(const int32_t messageId)
{
    this->messageId = messageId;
}

在使用时导入相应的头文件即可。

Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %
FranzKafka95
FranzKafka95

极客,文学爱好者。如果你也喜欢我,那你大可不必害羞。

文章: 86

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注

zh_CNCN