Parcelable 인터페이스를 구현할 때 부울을 읽고 쓰는 방법은 무엇입니까?


404

ArrayList Parcelable활동에 사용자 정의 객체 목록을 전달하기 위해 를 만들려고 합니다. 나는 myObjectList확장 ArrayList<myObject>하고 구현 하는 클래스를 작성하기 시작 합니다 Parcelable.

의 일부 속성 MyObjectboolean있지만 Parcel메소드가 없습니다 read/writeBoolean.

이것을 처리하는 가장 좋은 방법은 무엇입니까?


3
활동 사이에 객체를 전달하는 것에 대한 모든 독서는 직렬화 가능 대신 소포 가능 사용을 미리 설정하기 때문에.
grunk

10
@MisterSquonk Serializable상호 작용 통신에 인터페이스를 사용해서는 안됩니다 . 느립니다.
Octavian A. Damiean 2016 년

1
@ grunk : 좋아, 충분하지만 Intent.putExtra (String name, Serializable value)가 문서에서 더 이상 사용되지 않는 것으로 표시 될 때까지 인생이 더 편 해지면 계속 사용하게되어 기쁩니다. 그냥 생각이야
Squonk

3
@Octavian : 그러나 그것은 사례 별 연구에 의존하며 상대적입니다.
Squonk

2
내 의견으로는 안드로이드의 건축가 팀은 게으르다! 부울 어 is 어 !!!!!!!!
Mateus

답변:


942

내가하는 방법은 다음과 같습니다.

writeToParcel :

dest.writeByte((byte) (myBoolean ? 1 : 0));     //if myBoolean == true, byte == 1

readFromParcel :

myBoolean = in.readByte() != 0;     //myBoolean == true if byte != 0

38
바이트 오버 int를 사용할 이유가 없습니다. 캐스트 때문에 바이트가 더 장황합니다. dest.writeInt (myBoolean? 1 : 0);
Miguel

@SiPlus 주석이 왜 그렇게 많은 투표를 받았습니까? 1도 0도 "로드"되지 않습니다. 전혀 차이가 없습니다. 그리고 Java는 언제 약한 유형의 언어입니까?
아무도

13
@sotrh은 바이트를 쓰는 것만으로 int를 씁니다 :/** * Write a byte value into the parcel at the current dataPosition(), * growing dataCapacity() if needed. */ public final void writeByte(byte val) { writeInt(val); }
Dallas

3
@ 달라스는 문서에서 나온 것입니까? 그렇다면 내 의견을 무시하십시오. api가 말하는 함수를 가지고있는 것처럼 writeByte보이지만 실제로는 int를 씁니다.
sotrh

1
소스 코드의 복사-붙여 넣기 인 @sotrh. android.os.Parcel 소스를 열고 직접 확인하십시오.
Yaroslav Mytkalyk

66

writeValue 메소드를 사용할 수도 있습니다 . 제 생각에는 이것이 가장 간단한 해결책입니다.

dst.writeValue( myBool );

그런 다음 간단한 캐스트로 쉽게 검색 할 수 있습니다 Boolean.

boolean myBool = (Boolean) source.readValue( null );

후드 아래에서 Android Framework는 정수로 처리합니다.

writeInt( (Boolean) v ? 1 : 0 );

"후드 아래"부분을 표시하는 Android 소스 (l. 1219). (메소드 호출과 스위치로 인해) 조금 덜 효율적이지만이 방법은 조금 더 간단합니다.
desseim

6
여기에 작성된 코드는 컴파일되지 않습니다. readValue에는 클래스 로더가 필요하지만 부울에는 필요하지 않습니다. "boolean myBool = (Boolean) source.readValue (null);"이어야합니다. 그들이 무엇을하고 있는지 전혀 모르고이 답변에 대한 나의 편집을 거부 한 리뷰어 : @hemang, jeeped, DavidRR.
miguel

1
@miguel 그건 사실이야, 고쳐 :)
Taig

15

당신은 이렇게 선언합니다

 private boolean isSelectionRight;

쓰다

 out.writeInt(isSelectionRight ? 1 : 0);

읽다

isSelectionRight  = (in.readInt() == 0) ? false : true;

부울 형식은 Parcel이 지원하는 형식으로 변환해야하므로 int로 변환 할 수 있습니다.


이로 인해 오류가 발생하고 호환되지 않는 유형이 필요합니다. boolean found int?
Paul Okeke

12

클래스에서 Parcelable을 구현 한 후 AndroidStudio (2.3 atm 사용)를 사용하면 클래스 이름 위에 마우스 포인터를 놓으면 Parcelable 구현을 추가하라는 메시지가 표시됩니다.

여기에 이미지 설명을 입력하십시오

네 개의 필드에서 다음을 생성합니다.

public class YourClass implements Parcelable{

String someString;
int someInt;
boolean someBoolean;
List<String> someList;

protected YourClass(Parcel in) {
    someString = in.readString();
    someInt = in.readInt();
    someBoolean = in.readByte() != 0;
    someList = in.createStringArrayList();
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(someString);
    dest.writeInt(someInt);
    dest.writeByte((byte) (someBoolean ? 1 : 0));
    dest.writeStringList(someList);
}

...

이것은 편리합니다 :)
Dino Tw

8

나는 보통 그것들을 배열로 가지고 writeBooleanArray있고readBooleanArray

포장해야하는 단일 부울 인 경우 다음을 수행 할 수 있습니다.

parcel.writeBooleanArray(new boolean[] {myBool});

부울 몇 개를 소포해야 할 때 문제가 발생한 적이 있습니까? 도와주세요?> stackoverflow.com/questions/13463727/… . 감사.
Roger Alien

8
out.writeInt(mBool ? 1 : 0); //Write
this.mBool =in.readInt()==1; //Read

5

Android Studio를 사용하는 경우 Parcelable을 구현하는 가장 쉬운 방법을 제안했습니다.

파일-> 설정-> 플러그인-> 리포지토리 찾아보기 로 이동하여 소포를 검색하십시오.

여기에 이미지 설명을 입력하십시오 Parcelable이 자동으로 생성됩니다.

그리고 이것을하기위한 웹리스트도 있습니다. http://www.parcelabler.com/


4

nullable 지원으로 Kotlin 에서 짧고 간단한 구현 :

Parcel에 메소드 추가

fun Parcel.writeBoolean(flag: Boolean?) {
    when(flag) {
        true -> writeInt(1)
        false -> writeInt(0)
        else -> writeInt(-1)
    }
}

fun Parcel.readBoolean(): Boolean? {
    return when(readInt()) {
        1 -> true
        0 -> false
        else -> null
    }
}

그리고 그것을 사용하십시오 :

parcel.writeBoolean(isUserActive)

parcel.readBoolean()        // For true, false, null
parcel.readBoolean()!!      // For only true and false

@AliKazi 당신은 옵션 유형을 지원하는 Java의 한 줄 문장 으로이 작업을 수행 할 수 없습니다. 3 가지 상태를 유지해야합니다. 널 잊어 버린 것 같아
Pavel Shorokhov

@ comm1x, IDE는이 솔루션을 좋아하지 않습니다. `수퍼 클래스 생성자가 호출되기 전에 "readBoolean"에 액세스 할 수 없습니다.
Adam Hurwitz

@ comm1x 문제를 해결했습니다. 추가 된 메소드가 작동하려면 동반 객체
Adam Hurwitz

3

마스킹 및 시프트를 사용하여 부울 값을 바이트로 묶을 수 있습니다. 그렇게하는 것이 가장 효율적인 방법 일 것입니다.


+1. 사실, 바이트 단위로 값을 저장하는 것이 더 효율적입니다. 아이디어를 표현하기 위해 내 질문을 편집 해 주시겠습니까?
Octavian A. Damiean 2016 년

당신은 할 수 있지만, 당신이 쓴 것은 실제로 내가 의도 한 것이 아닙니다. 작동하지만 가장 효율적인 것은 아닙니다. 당신은 마스크와 부울 대수를 사용하여 바이트에 8 개 논리 값을 포장 할 수
fleetway76을

대부분의 경우 나는 당신에게 동의하지만, 부울이 작동하는 세 가지 상태가 필요한 경우가 종종 있습니다. 선택적인 예 / 아니오 질문과 같은. 부울이 명시 적으로 지정되었는지 여부를 확인하려면 null이 필요합니다.
Chad Gorshing

Parcel의 writeByte()메소드가 직접 호출하기 때문에 byte over int를 사용하는 이유는 없습니다writeInt()
Yaroslav Mytkalyk

3

여기서 실제 질문을 식별하기는 어렵습니다. Parcelable인터페이스를 구현할 때 부울을 처리하는 방법이라고 생각합니다 .

MyObject의 일부 속성은 부울이지만 Parcel에는 read / writeBoolean 메서드가 없습니다.

값을 문자열 또는 바이트로 저장해야합니다. 문자열 을 찾으면 부울 값을 구문 분석하기 위해 String호출 된 클래스 의 정적 메소드를 사용해야합니다 valueOf(). 바이트 단위로 저장하는 것만 큼 효과적이지 않습니다.

String.valueOf(theBoolean);

바이트를 찾으면 직접 변환 논리를 구현해야합니다.

byte convBool = -1;
if (theBoolean) {
    convBool = 1;
} else {
    convBool = 0;
}

Parcel객체를 비 정렬화할 때는 원래 유형으로 변환해야합니다.


String을 사용할 이유가 전혀 없습니다. Parcel의 writeByte()메소드가 직접을 호출하기 때문에 byte over int를 사용할 이유가 없습니다 writeInt(). 변환 논리가 너무 장황합니다. 그냥 writeInt(boolean ? 1 : 0)하고boolean = readInt() != 0
Yaroslav Mytkalyk

1

이 질문은 당신이 스스로하고 싶다면 다른 사람들에 의해 이미 완벽하게 대답되었습니다.

하위 수준의 소포 코드를 대부분 캡슐화하거나 숨기려면 소포 처리를 단순화하기 위해 얼마 전에 작성한 코드 중 일부를 사용하는 것이 좋습니다.

소포에 쓰는 것은 다음과 같이 쉽습니다.

parcelValues(dest, name, maxSpeed, weight, wheels, color, isDriving);

여기서 색상은 열거 형이고 isDriving은 부울입니다.

소포에서 읽는 것도 그리 어렵지 않습니다.

color = (CarColor)unparcelValue(CarColor.class.getClassLoader());
isDriving = (Boolean)unparcelValue();

프로젝트에 추가 한 "ParceldroidExample"을 살펴보십시오.

마지막으로 CREATOR 이니셜 라이저를 짧게 유지합니다.

public static final Parcelable.Creator<Car> CREATOR =
    Parceldroid.getCreatorForClass(Car.class);

감사합니다 .class.getClassLoader().
CoolMind

0

Android (AOSP) 소스에는 많은 예제가 있습니다. 예를 들어, PackageInfo클래스에는 부울 멤버 requiredForAllUsers가 있으며 다음과 같이 직렬화됩니다.

public void writeToParcel(Parcel dest, int parcelableFlags) {
    ...
    dest.writeInt(requiredForAllUsers ? 1 : 0);
    ...
}

private PackageInfo(Parcel source) {
    ...
    requiredForAllUsers = source.readInt() != 0;
    ...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.