Parcelable arabirimini uygularken bir boole nasıl okunur / yazılır?


404

ArrayList ParcelableBir etkinliğe özel nesne listesi geçmek için bir yapmaya çalışıyorum . myObjectListGenişleyen ArrayList<myObject>ve uygulayan bir sınıf yazmaya başladım Parcelable.

Öğesinin bazı öznitelikleri MyObjectvardır booleanancak Parcelherhangi bir yöntemi yoktur read/writeBoolean.

Bununla başa çıkmanın en iyi yolu nedir?


3
Çünkü aktiviteler arasında nesne geçirme ile ilgili yaptığım tüm okumalar serialisable yerine parcelable kullanımını ön planda tutar.
grunk

10
@MisterSquonk SerializableArayüzü etkinlikler arası iletişim için kullanmamalısınız . Bu yavaş.
Octavian A. Damiean

1
@grunk: Tamam, bu yeterince adil, ancak Intent.putExtra (Dize adı, Serileştirilebilir değer) dokümanlarda kullanımdan kaldırılmış olarak işaretleninceye kadar, hayatı benim için kolaylaştırırsa kullanmaya devam etmekten mutluluk duyacağım. Sadece bir düşünce.
Squonk

3
@Octavian: Ancak bu vaka başına bir çalışmaya bağlıdır ve görecelidir.
Squonk

2
benim düşünceme göre, android mimar ekibi tembel !!! whereis boolean !!!!!!!!
Mateus

Yanıtlar:


942

İşte böyle yapardım ...

writeToParcel:

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

readFromParcel:

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

38
İnt yerine bayt kullanmak için bir sebep yok. byte, cast nedeniyle daha ayrıntılı: dest.writeInt (myBoolean? 1: 0);
miguel

@SiPlus yorumu neden bu kadar çok oy aldı? Ne 1 ne de 0 hiç yüklü değil. Hiç fark etmez. Java ne zamandan beri zayıf yazılan bir dildir?
kimse

13
@sotrh bir bayt yazmak sadece bir int yazıyor:/** * 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
@Dallas bu belgelerden mi? Eğer öyleyse yorumumu dikkate almayın. API'nin söyleyen bir işlevi olması çok garip görünüyor writeByte, ama aslında bir int yazıyor.
sotrh

1
@sotrh bu bir kaynak kodundan kopyala-yapıştır. Android.os.Parcel kaynağını açın ve kendiniz görün.
Yaroslav Mytkalyk

66

Ayrıca writeValue yöntemini de kullanabilirsiniz . Bence bu en basit çözüm.

dst.writeValue( myBool );

Daha sonra basit bir oyuncu kadrosu ile kolayca alabilirsiniz Boolean:

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

Başlık altında Android Framework bir tamsayı olarak ele alacaktır:

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

"kaputun altında" bölümünü gösteren android kaynağı (l. 1219). Biraz daha az verimli olmasına rağmen (yöntem çağrısı ve anahtar nedeniyle) bu yöntem biraz daha basit okunur.
desseim

6
Burada yazılan kod derlenmeyecektir. readValue bir sınıf yükleyici gerektirir ancak Booleans için gerekli değildir. "Boolean myBool = (Boolean) source.readValue (null);" Ne yaptıkları hakkında hiçbir fikri olmayan ve bu cevaba yapılan düzenlememi reddeden yorumcular: @hemang, jeeped, DavidRR.
miguel

1
@miguel Doğru, düzeltildi :)
Taig

15

böyle beyan ediyorsun

 private boolean isSelectionRight;

yazmak

 out.writeInt(isSelectionRight ? 1 : 0);

okumak

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

boolean tipinin Parsel'in desteklediği bir şeye dönüştürülmesi gerekir ve böylece int'e dönüştürebiliriz.


Bu bir hata, uyumsuz türleri, gerekli boole bulunan int neden olur?
Paul Okeke

12

AndroidStudio (2.3 atm kullanarak), sınıfınıza Parcelable'ı uyguladıktan sonra, fare işaretçinizi sınıf adınızın üzerinde tutmanız yeterlidir ve parcelable uygulamasını eklemenizi ister:

resim açıklamasını buraya girin

Dört alandan aşağıdakileri üretir:

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

...

Bu kullanışlı :)
Dino Tw

8

Normalde onları bir dizi ve çağrı var writeBooleanArrayvereadBooleanArray

Paketlemeniz gereken tek bir boolean ise, bunu yapabilirsiniz:

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

Birkaç boolean paketlemeniz gerektiğinde hiç sorunla karşılaştınız mı? Lütfen bana yardım edebilir misin? stackoverflow.com/questions/13463727/… . Teşekkürler.
Roger Alien

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

5

Android Studio kullanıyorsanız Parcelable'ı uygulamanın en kolay yolunu önerdim.

Sadece Dosya-> Ayarlar-> Eklentiler-> Depoya Gözat'a gidin ve parcelable öğesini arayın.

resim açıklamasını buraya girin Otomatik olarak Parcelable oluşturur.

Bunu yapmak için de bir webiste var. http://www.parcelabler.com/


4

Kotlin'de null edilebilir destekle kısa ve basit uygulama :

Parsel'e yöntem ekleme

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

Ve kullanın:

parcel.writeBoolean(isUserActive)

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

@AliKazi bunu isteğe bağlı destek türleriyle Java'da 1 satır ifadesinde yapamazsınız. 3 eyalette ısrar etmelisin. Sanırım null'u unuttun.
Pavel Shorokhov

@ comm1x, IDE bu çözümü sevmiyor. Üst sınıf yapıcı çağrılmadan önce "readBoolean" a erişilemiyor.
Adam Hurwitz

@ comm1x Sorunu çözdüm. Çalışmak için eklenen yöntemlerin tamamlayıcı nesne
Adam Hurwitz

3

Boole değerlerinizi maskeleme ve kaydırma özelliğini kullanarak bir bayta paketleyebilirsiniz. Bunu yapmanın en etkili yolu olurdu ve muhtemelen sizden beklediğiniz şey budur.


+1. Doğru, değeri bir baytta kaydetmek daha verimli olacaktır. Fikrimi temsil etmek için sorumu düzenlememi ister misiniz?
Octavian A. Damiean

Yapabilirsiniz, ama yazdıklarınız aslında kastettiğim şey değil. Çalışacak ama en verimli değil. Maskeleri ve boole cebirini kullanarak 8 boole
değerini

Çoğu durumda size katılıyorum, ancak zaman zaman Boolean'ın çalışacağı üç duruma ihtiyacım olan sürünen davalarım var. İsteğe bağlı bir evet / hayır sorusu gibi. Boole açıkça belirtilmiş olup olmadığını bilmek null gerekir.
Chad Gorshing

writeByte()writeInt()
Bayt'ın

3

Burada gerçek soruyu tanımlamak zor. ParcelableArayüzü uygularken booleans ile nasıl başa çıkılacağını tahmin ediyorum .

MyObject öğesinin bazı öznitelikleri boole'dir ancak Parcel'in read / writeBoolean yöntemi yoktur.

Değeri dize veya bayt olarak depolamanız gerekir. Bir dize için giderseniz , boolean değerini ayrıştırmak için Stringçağrılan sınıfın statik yöntemini kullanmanız gerekir valueOf(). Zor bir baytta kaydetmek kadar etkili değildir.

String.valueOf(theBoolean);

Bir bayt için giderseniz, bir dönüşüm mantığı kendiniz uygulamanız gerekir.

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

ParcelNesneyi kaldırırken orijinal türe dönüştürme işlemine dikkat etmelisiniz.


String'i kullanmak için kesinlikle hiçbir neden yoktur. Parsel writeByte()yöntemi doğrudan çağırdığı için bayt int kullanmanın bir nedeni yoktur writeInt(). Dönüşüm mantığı çok ayrıntılı. Sadece yap writeInt(boolean ? 1 : 0)veboolean = readInt() != 0
Yaroslav Mytkalyk

1

Kendi başınıza yapmak istiyorsanız, bu soru zaten diğer insanlar tarafından mükemmel bir şekilde cevaplanmıştır.

Düşük düzeyli parsel kodunun çoğunu kapsüllemeyi veya gizlemeyi tercih ediyorsanız , parcelables kullanımını kolaylaştırmak için bir süre önce yazdığım bazı kodları kullanmayı düşünebilirsiniz .

Bir pakete yazmak şu kadar kolaydır:

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

rengin bir enum ve isDriving'in bir boole olduğu.

Bir paketten okumak da çok zor değil:

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

Projeye eklediğim "ParceldroidExample" ye bir bakın.

Son olarak, CREATOR başlatıcıyı kısa tutar:

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

İçin teşekkürler .class.getClassLoader() .
CoolMind

0

Android (AOSP) kaynaklarında birçok örnek var. Örneğin, PackageInfosınıfın bir boole üyesi vardır requiredForAllUsersve aşağıdaki gibi serileştirilir:

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

private PackageInfo(Parcel source) {
    ...
    requiredForAllUsers = source.readInt() != 0;
    ...
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.