2017-05-26 16 views
5

Tôi đã được viết Parcelable s để Parcel mà không tập trung vào lĩnh vực cờ, mà là một tham số trong chữ ký phương pháp và nó đã làm việc tốt nhưng tôi đã chạy vào một thực hiện nơi tôi không còn có thể bỏ qua chúng:Việc sử dụng cờ trong Bưu kiện là gì?

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); 
      } 
     } 
    } 

Đây là một Mapđến/từParcelable tiện ích tôi đã viết và tôi tự hỏi nếu cờ nên được thông qua vì nó là cả chính cũng như Value khi viết họ hoặc phải vượt qua 0 cho Khóaflags cho Giá trị.

tôi đọc định nghĩa của những gì một lá cờ là trong docs:

PARCELABLE_WRITE_RETURN_VALUE

thêm vào mức API 1

int PARCELABLE_WRITE_RETURN_VALUE 

Cờ để sử dụng với writeToParcel(Parcel, int): đối tượng là được viết là giá trị trả về, đó là kết quả của một hàm như "Parcelable someFunction()", "void someFunction (trong Parcelable)", hoặc "void someFunction (inout Parcelable)". Một số triển khai có thể muốn phát hành tài nguyên tại thời điểm này.

Giá trị không đổi: 1 (0x00000001)

Nhưng tôi không thể hiểu được nó. Bất cứ ai có thể giải thích trong điều kiện đơn giản những gì một lá cờ Parcelable là gì và làm thế nào nó nên được sử dụng?

+0

"một giá trị trả về, đó là kết quả của một hàm" là khá tự giải thích –

+0

@ cricket_007: \t Tôi có một phương pháp khoảng trống ?? Nhưng đó là một phương pháp tĩnh? Điều đó có liên quan gì với mọi thứ? Nếu bạn gọi phương thức này, entry.getKey() sau đó, nó sẽ trả về một Parcelable. Không phải lá cờ sẽ là 1? –

+0

'void write' là phương thức của bạn,' entry.getKey() 'được định nghĩa trong giao diện Bản đồ, tôi không hiểu điểm của bạn –

Trả lời

0

Bạn chỉ có thể cung cấp cờ số không hoặc một.

Bạn có một phương thức void, vì vậy bạn không trả về Parcelable từ một hàm hay bạn có tham số Parcelable, như tài liệu nói, do đó cờ phải bằng 0.

3

Cờ hiện tại duy nhất (PARCELABLE_WRITE_RETURN_VALUE) được thiết kế để sử dụng trong giao diện AIDL. Nó được cho là gợi ý một số loại đối tượng Parcelable, rằng chúng đang được trả về từ phương thức IPC, do đó các tài nguyên liên quan của chúng có thể được giải phóng. Fot dụ, ContentProvider trong nội bộ chứa phương pháp AIDL như thế này:

ParcelFileDescriptor openFile(String path, int flags); 

Khi bạn ghi đè openFile trong một ContentProvider tùy chỉnh, phương pháp của bạn trả về một mở ParcelFileDescriptor ... You are not đóng cửa đó cho mình, và nó không phải là tự động đóng lại trong quá trình chuyển đổi giữa các quá trình hoặc (chuyển các bộ mô tả giữa các tiến trình không ngụ ý đóng chúng trong Linux). Nhưng bộ mô tả không bị rò rỉ!Thay vào đó, ParcelFileDescriptor closes itself khi ghi vào Parcel:

@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); 
     } 
    } 
} 

Kể từ ParcelFileDescriptor chỉ là loại thông dụng, sử dụng cơ sở vật chất của Binder/Parcel để vượt qua đặc tả tập tin giữa các quá trình, bạn có thể tưởng tượng được sự tồn tại của các lớp học tương tự, mà giữ được nguồn lực tự nhiên (bộ nhớ , các bộ mô tả tệp) và phát hành chúng một cách có điều kiện khi được trả về từ các phương thức giống như openFile.

Tương tự như vậy, các cờ khác có thể được sử dụng để tuyên truyền hành vi có điều kiện tương tự sâu xuống Matryoshka linh hoạt. Rất tiếc, các nhà phát triển Android chưa xác định các quy tắc hợp lý để giới thiệu các cờ tùy chỉnh như vậy (không giống như IBinder#FIRST_CALL_TRANSACTIONIBinder#LAST_CALL_TRANSACTION) và AIDL không được sử dụng rộng rãi trong thực tế bên ngoài nội dung Android, vì vậy tôi không biết bất kỳ ví dụ nào về các cờ như vậy.

+0

Được rồi, cho tôi biết nếu tôi đã hiểu chính xác. Phương thức open() dẫn đến một IPC và ở phía bên kia (một tiến trình khác), một FileDescriptor được tạo ra để được trả về cuối cùng cho chúng ta và bởi vì FileDescriptor có thể đã được mở ở bên đó, kiểm tra chỉ đóng trước khi gửi nó cho chúng ta . Ngoài ra, việc đóng tài nguyên ngay trước khi gửi qua cuộc gọi IPC là một trường hợp rất cụ thể và tôi cần tìm kiếm nó chỉ trong IPC. –

+1

@pulp_fiction Có, bạn đã nhận được tất cả các quyền. Ngoài ra, câu trả lời này chỉ * xấp xỉ * đúng, bởi vì bộ mô tả không thực sự "đóng trước khi gửi" - nó được nhân bản (bên trong 'writeFileDescriptor'), * nguyên bản * là" đóng "(không thực sự, vì các mô tả được tính tham chiếu)), sau đó lệnh dupe thực sự bị đóng (có lẽ trong quá trình chuyển, mâu thuẫn với tuyên bố trước đó của tôi, rằng các mô tả không bị đóng trong quá trình chuyển). Tất cả sự điên rồ đó được ẩn đằng sau sự trừu tượng của ParcelFileDescriptor, làm cho nó trông giống như "đóng cửa trước khi gửi". Họ đang nghĩ gì… – user1643723

+1

@pulp_fiction TL; DR: đừng cẩu thả lưu trữ FileDescriptors trong mọi thứ, nếu không Dianne Hackborn sẽ đến và giết con chó của bạn. Có một [phương pháp tiện dụng] (https://developer.android.com/reference/android/os/Parcel.html#hasFileDescriptors()) chỉ dành cho mục đích đó (để xác định xem Bưu kiện có chứa các bộ mô tả tệp) hay không. – user1643723

Các vấn đề liên quan