2017-05-26 89 views
5

我一直在写Parcelable s到Parcel没有任何专注于标志字段,这是在方法签名的参数,它一直很好,但我遇到了一个实现,我再也不能忽视他们:Parcelable中的标志有什么用处?

public static <K extends Parcelable, V extends Parcelable> void write(Parcel dest, 
                Map<K, V> map, int flags) { 
     if (map == null) { 
      dest.writeInt(-1); 
     } else { 
      Set<Map.Entry<K, V>> entrySet = map.entrySet(); 
      dest.writeInt(entrySet.size()); 
      for (Map.Entry<K, V> entry : entrySet) { 
       dest.writeParcelable(entry.getKey(), flags); 
       dest.writeParcelable(entry.getValue(), flags); 
      } 
     } 
    } 

这是一个Map向/从Parcelable公用事业我已经写了,我想知道如果标志应传递,因为它是既重点还有价值而写他们还是应该传递0密钥flags for Value

我看了一个什么样的标志是在docs定义:

PARCELABLE_WRITE_RETURN_VALUE

API等级加1

int PARCELABLE_WRITE_RETURN_VALUE 

标志为使用writeToParcel(Parcel, int):被写入的对象是 是一个返回值,这是一个功能,诸如 “Parcelable someFunction()”“空隙someFunction(出Parcelable)”,或“空隙someFunction(INOUT Parcelable)”的结果。有些 实现可能希望在此时释放资源。

恒值:1(00000001)

但我无法理解它。任何人都可以简单地解释一下Parcelable标志是什么以及它应该如何使用?

+0

“返回值,这是一个函数的结果”是非常自我解释 –

+0

@ cricket_007: \t 我有一个空隙方法??但这是一个静态方法?这与什么有关?如果你引用了方法entry.getKey(),那么它确实返回一个Parcelable。国旗不应该是1吗? –

+0

'void write'是你的方法,'entry.getKey()'是在Map接口中定义的,我不明白你的观点 –

回答

0

您只能提供标志零或一个。

你有一个void方法,所以你没有从函数返回一个Parcelable,也没有参数是Parcelable,正如文档所说,因此该标志应该是零。

3

当前唯一的标志(PARCELABLE_WRITE_RETURN_VALUE)旨在用于AIDL接口。它应该提示某些Parcelable对象,它们是从IPC方法返回的,因此它们的关联资源可以被释放。 FOT例如,ContentProvider的内部含有AIDL方法是这样的:

ParcelFileDescriptor openFile(String path, int flags); 

当您覆写了定制的ContentProvider openFile,你的方法返回一个开放 ParcelFileDescriptor ......你自己都没有关闭它,它不会自动关闭在进程间传输过程中(在进程间传递描述符并不意味着在Linux中关闭它们)。但描述符不泄漏!相反,ParcelFileDescriptor closes itself时写入地块:

@Override 
public void writeToParcel(Parcel out, int flags) { 
    if (mWrapped != null) { 
     try { 
      mWrapped.writeToParcel(out, flags); 
     } finally { 
      releaseResources(); 
     } 
    } else { 
     if (mCommFd != null) { 
      out.writeInt(1); 
      out.writeFileDescriptor(mFd); 
      out.writeFileDescriptor(mCommFd); 
     } else { 
      out.writeInt(0); 
      out.writeFileDescriptor(mFd); 
     } 
     if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) { 
      // Not a real close, so emit no status 
      closeWithStatus(Status.SILENCE, null); 
     } 
    } 
} 

由于ParcelFileDescriptor只是普通的类,使用捆扎机/包裹的设施,流程之间传递的FileDescriptor,你能想象类似的类,即守住本土资源(内存存在,文件描述符),并在从类似openFile的方法返回时有条件地释放它们。

同样,其他标志可能被用来传播类似的条件行为深入Parcelable matryoshka。不幸的是,Android开发者并没有定义合理的规则来引入这样的自定义标志(例如IBinder#FIRST_CALL_TRANSACTIONIBinder#LAST_CALL_TRANSACTION),并且AIDL在Android内部实践中并未广泛使用,所以我不知道这些标志的任何示例。

+0

好的,告诉我,如果我已经正确理解它。 open()方法产生一个IPC,另一方面(另一个进程),创建一个FileDescriptor以最终返回给我们,并且由于FileDescriptor可能已经在这一侧打开,所以在将它发送给我们之前,检查会关闭。另外,在通过IPC调用发送之前关闭资源是一个非常特殊的情况,我只需要在IPC期间查看它。 –

+1

@pulp_fiction是的,你知道了。此外,这个答案只是*大致*真实的,因为描述符在发送之前并不实际“关闭” - 它被复制(在'writeFileDescriptor'内部),* original *是“关闭的”(不是真的,因为描述符是引用计数),那么这个骗局是真正关闭的(大概在转移期间,与我之前的说法相矛盾,描述符在转移过程中没有关闭)。所有这些疯狂都隐藏在ParcelFileDescriptor抽象背后,使得它看起来像“在发送之前关闭”。他们在想什么...... – user1643723

+1

@pulp_fiction TL; DR:不要不小心把FileDescriptors存储在东西里,否则Dianne Hackborn会来杀你的狗。有一个[方便的方法](https://developer.android.com/reference/android/os/Parcel.html#hasFileDescriptors())仅用于此目的(以确定Parcel是否包含文件描述符)。 – user1643723