2017-05-26 40 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