很久之前就看到有网友遇到用Parcel传Bitmap的时候,会遇到因为图片太大而报错,都在讨论传输Bitmap的时候的大小限制,但是实际上应该只有在4.0之前会有限制,4.0之后图片传输的方式有变化,它采用了Blob来传输,最终会使用ashmem来传递占用内存大的数据。下面分别介绍4.0前后Parcel对图片传输的异同。
Parcel写入读取
先简单介绍一下Parcel的写入读取模式,Parcel是Android中跨进程数据传递的中介,跨进程数据使用Parcel传递效率会比Serializable。Parcel提供了很多接口,比如writeInt,writeFloat,writeString,readInt,readFloat,readString等等,用这些接口可以读取写入数据.而实际上,Parcel里面有一个mData变量:
void* mData;
这个变量是一个指针类型,那些写入的接口都是将数据写入到这个指针变量指向的区域,读取也是从mData中读,写入和读取的数据相互对应。然后再将这个mData传入到Binder,或者是从Binder中读取出来。
2.3源码
在2.3中,Android Parcel传输图片是有大小限制的,实际上的限制应该是Binder对传输的数据大小的限制。Bitmap会对应的native层Parcel传输函数是Bitmap_writeToParcel,先看源码是怎么传输的:
static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
const SkBitmap* bitmap,
jboolean isMutable, jint density,
jobject parcel) {
if (parcel == NULL) {
SkDebugf("------- writeToParcel null parcel\n");
return false;
}
android::Parcel* p = android::parcelForJavaObject(env, parcel);
p->writeInt32(isMutable);
p->writeInt32(bitmap->config());
p->writeInt32(bitmap->width());
p->writeInt32(bitmap->height());
p->writeInt32(bitmap->rowBytes());
p->writeInt32(density); //这些都是写入到Parcel的mData
if (bitmap->getConfig() == SkBitmap::kIndex8_Config) {
SkColorTable* ctable = bitmap->getColorTable();
if (ctable != NULL) {
int count = ctable->count();
p->writeInt32(count);
memcpy(p->writeInplace(count * sizeof(SkP