Physical Address:
ChongQing,China.
WebSite:
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++两种后端语言给出示例。
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++来实现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;
}
在使用时导入相应的头文件即可。